Detecting user activity/inactivity in a Windows Mobile app

Saturday, January 9, 2010


There doesn't appear to be a simple API call on Windows Mobile or Windows CE to get the amount of time that the user has been idle. For example, maybe you want to pop up a dialog box or quit your app if the user hasn't done anything for more than 5 minutes. A quick search might turn up GetIdleTime(), but that function is for CPU idle time, not user idle time.

Most recent Windows Mobile devices use a Power Manager, which keeps track of this stuff. You can use the named activity timers "PowerManager/UserActivity_Active" and "PowerManager/UserActivity_Inactive" to detect when the user has become active and inactive. On the couple of devices I looked at, these events have timing resolutions of 100 ms, which is good enough for most purposes and won't cause your code to peg the CPU by constantly firing events. However, there does not appear to be any guarantee that these two activity timers actually exist and function correctly on every device.

Below is a code snippet that uses these events in managed code:

private const EVENT_ALL_ACCESS = 0x1F0003;
private const ActiveName = "PowerManager/UserActivity_Active";
private const InactiveName = "PowerManager/UserActivity_Inactive";

[DllImport("coredll.dll")]
private static extern IntPtr OpenEvent(int desiredAccess, bool inheritHandle, string name);
[DllImport("coredll.dll")]
private static extern int WaitForSingleObject(IntPtr handle, int milliseconds);

public static void Main(string[] args) {
  IntPtr activitySignal = OpenEvent(EVENT_ALL_ACCESS, false, ActiveName);
  IntPtr inactivitySignal = OpenEvent(EVENT_ALL_ACCESS, false, InactiveName);
  if(activitySignal == IntPtr.Zero || inactivitySignal == IntPtr.Zero) {
    // Can't open the events -- this device probably doesn't define them
    return;
  }
  while(true) {
    WaitForSingleObject(activitySignal, int.MaxValue);
    WriteLine("User is now active.");
    WaitForSingleObject(inactivitySignal, int.MaxValue);
    WriteLine("User is now inactive.");
  }
}

Given this code, it is then fairly trivial to figure out whether the user is currently active and if not, how long the user has been inactive. It's also easy to write a function that performs some action (like calling a callback) once the user has been idle for some amount of time.

Tags: idle, inactivity, wince, winmo | Posted at 13:09 | Comments (2)


Comments

Pam on Wednesday, April 21, 2010 at 08:56

Great article, very helpful.
According to the MSDN page (http://msdn.microsoft.com/en-us/library/ee497763.aspx) you can create these events by modifying the registry values of [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\ActivityTimers\SystemActivity].

Pam on Wednesday, April 21, 2010 at 09:00

BTW, i love your dog pictures :)

Add a comment

Name:
Email: (optional, not displayed to public)
URL: (do not fill this in — leave blank!)

Comment: