Jerry Nixon @Work: Mango Sample: Lock and Run

Jerry Nixon on Windows

Monday, November 28, 2011

Mango Sample: Lock and Run

imageWhen a user is idle, their screen locks and your Windows Phone application is suspended. This might be undesired, like for:  a timer, certain games, and driving directions.

We have two properties to consider:

  1. The UserIdleDetectionMode property
  2. The ApplicationIdleDetectionMode property
Read this from MSDN:  For the best user experience in applications that target Windows Phone OS 7.1, Microsoft strongly recommends that you utilize the following new features while your application runs under lock, instead of setting theApplicationIdleDetectionMode property:
  • Fast Application Switching, a built-in feature of the OS that provides substantial improvements to state maintenance and performance when an application moves to and from the background.
  • Background agent features, as described in Multitasking for Windows Phone, for scenarios such as background transfers and background audio playback.

Speed up Resume?

I suspected suspending idle would speed up application resume. We only have one second to resume when reactivated. But, MSDN returns our attention to fast switching. It’s really is fast, and automatic:
From MSDN: Applications targeted to Windows Phone OS 7.1 go into a dormant state when the lock screen engages and, when the phone unlocks, quickly resume to exactly the same state in which they entered dormancy. This is all accomplished automatically and without the drain on the battery or potential hidden data plan cost to the user that disabling idle detection introduces.

Perhaps we do it anyway? No!

From MSDN: Do not disable application idle detection to speed up application resume. Doing so will not improve performance or application state maintenance, but will cause your application to drain the device battery more quickly, causing a negative user experience.

Do better: Roll your own Idle

Here’s the problem: we disabled idle detection – but the user is REALLY idle? Now, our application is just bleeding the battery. We must detect some type of idle our own way:
From MSDN: It is recommended that applications that disable user idle detection implement their own form of idle detection and enable UserIdleDetectionMode when appropriate. For example, an accelerometer-based game could enable user idle detection if the accelerometer shows no activity for a period of time.

Option 1: UserIdleDetectionMode

This property allows your application to continue running when the user is not physically interacting with the phone. Default = IdleDetectionMode.Enabled. The operating system considers the user to be idle when they have not touched the screen or the hardware buttons within the device lock timeout window, specified in the device’s Settings page.
From MSDN: This feature should be used with caution. Applications that disable user idle detection will continue to run and consume battery power when the user is not using the phone.
So, if you set UserIdleDetectionMode to Disabled the Lock Screen will never engage. This means your application will remain visible no matter what happens.

Here’s how you use it:

image

In the code above, we are Disabling and Enabling User Idle Detection. Of course, in a real application we would do this based on certain events of user interaction.

Option 2: ApplicationIdleDetectionMode
This property allows your application to continue when the user’s phone has locked. Default = IdleDetectionMode.Enabled. The operating system considers an application to be idle if the user has allowed the phone to lock.
From MSDN: In future releases, the conditions that qualify an application as idle may change. Even if application idle detection is disabled, the operating system may deactivate an application for other reasons, such as a depleted battery.
So, if you set ApplicationIdleDetectionMode to Disabled the Lock Screen will still engage, but your application will continue to run while Locked.


Here’s how you use it:

image

In the code above, see where we set Application Idle Detection to Enabled? This will fail. Application Idle Detection cannot be set to Enabled (an InvalidOperationException is thrown). In fact, there are two items worth noting:
  1. ApplicationIdleDetectionMode cannot be enabled after it has been disabled.
  2. ApplicationIdleDetectionMode cannot be set until the application’s PhoneApplicationFrame object has been initialized.
This limitation has implications. Should you allow a user to Disable Idle Detection, you will likely allow them to Enable it. Of course, based on the information above, this would be impossible.

How to Choose

If your application wants to re-Enable Idle Detection based on an event or user interaction, you must choose UserIdleDetectionMode. If you want to operate WHILE the Lock Screen is engaged, you must choose ApplicationIdleDetectionMode.

Ready Matlock? The Windows Phone 7.0 Application Certification Requirement used to read: “an application running under a locked screen must first ask the user for permission to do so” and that “the user must be able to configure this functionality from the application’s UI.” In fact the test case used to state “prompt the user for explicit permission to run under a locked screen upon first use of ApplicationIdleDetectionMode”

However, the Windows Phone 7.1 Application Certification Requirement reads:

Requirement 6.3: Applications Running under a Locked Screen

  • 6.3.1 - Minimize Power Usage When Running Under a Locked Screen: All applications that run under a locked screen must stop any UI updates, active timers, and other non-critical processing when notified that the screen is locked.
  • 6.3.2 - Applications that play audio under a locked screen
  • 6.3.2.1 - Audio Playback and Battery Life Under a Locked Screen: The minimum battery life of the phone must be greater than six hours while the application plays audio under a locked screen.
  • 6.3.2.2 - Idle Behavior Under a Locked Screen: If an application is not playing audio when the phone is locked, the application must remain idle while the phone screen is locked.
  • 6.3.3 - Applications that do not play audio under a locked screen
  • 6.3.3.1 - Minimum Battery Life Under a Locked Screen: The minimum battery life of the phone must be greater than 120 hours while the application is running under a locked screen.
In the list above, I hope you noticed the lack requirement to explicitly ask the user for permission to continue running while locked. This means, as I understand it, that your application should be approved for the Marketplace even if you do not prompt the user.

SampleDo better: Ask the User

Always ask the user. You heard me. Disregard the official certification requirement – can he say that? Listen, you might want your application to run under the Lock Screen. But more than that, you want your application to remain installed! Don’t assume the user’s configuration preferences.
Note: The requirement might revert! Keep the configuration UI. But if you like to ride on the wild side, default Idle Detection to Disabled. That’s a compromise.

The configuration UI’s XAML is simple:

image

In the code above, see the ToggleSwitch? That control is the standard Windows Phone checkbox. However, it is not a standard Windows Phone control. If you want the ToggleSwitch in your application, download our free Silverlight Toolkit for Windows Phone @ CodePlex.

Code-behind implementation could be this easy:

image

Do better: Detect Lock

Your application is considered to be the Frame (or Page). The OS is considered to be the Shell. When the Shell covers your application’s Frame, then the Obscured event is raised. When the Shell no longer covers your application’s Frame, then the Unobscured event is raised.

You might be wondering, is the Lock Screen obscuring my application, is a Phone Call obscuring my application, or is the Start Menu obscuring my application? These are the questions that will plague us – we cannot know (and, who cares?)
Here’s MSDN: There is no indication of which piece or pieces of the shell chrome are obscuring the application. An application will get the Obscured event immediately after coming to the foreground if there is already some UI covering the screen. However, the event is not raised when the application is navigated away from during usage.
Here’s how to detect when our Application is Obscured by something:

image

In the code above, see the Obscured handler? If your Windows Phone application runs with Lock Screen is engaged, here you can reduce power and bandwidth consumption with things like:
  1. Stop timers using System.Threading.Timer.Dispose and DispatcherTimer.Stop
  2. Stop animations Storyboard.Pause or Storyboard.Stop
  3. Stop the Accelerometer by calling Stop (no data is returned anyway)
  4. Stop the Location Service by calling Stop
  5. Stop the FM radio by setting PowerMode to Off
  6. Prevent any new network requests
  7. Prevent any new isolated storage operations
  8. XNA games should return on Update()
  9. Set Microsoft.Xna.Framework.Game.InactiveSleepTime to 1
  10. Set MediaElement.Source to null

Conclusion

We generally recommend  Windows Phone applications do not run while locked. This is because Application Fast Switching (FAS) covers 90% of those  scenarios. However, we recognize there is an application class needing to continue while locked.

  • If you want to prevent the Lock Screen: UserIdleDetectionMode
  • If you want to run while Locked: ApplicationIdleDetectionMode

Best of luck, developer!