How to prevent screen locks in your UWP apps

News Feed

After a certain amount of idle time, Windows 10 devices may dim the display, activate the lock screen, or power down the display in order to conserve power. The amount of idle time required before this occurs depends on a device’s user settings. Unfortunately, this can turn out to be an inconvenient mistake if your app happens to be a passive experience like a video player, a music player, or a navigation app. Although users may be very engaged, Windows 10 devices will register watching and listening as user idle time since there is no direct interaction with the screen. How do you do this in UWP? The syntax turns out to be equally simple. You just need to make a display request call.

Note: If you’re still using Windows Phone Silverlight development, the correct way to handle this is to disable user idle detection.

Remember to lock up when you’re done

Following a call like this, the display will stay active until either…

you release the request with a RequestRelease() call

the app is no longer in the foreground

The DisplayRequest class basically only has two methods: RequestActive() and RequestRelease(). With it, you can make a request to keep the display active or you can withdraw your request.

There are two restrictions you need to be aware of about how to use these calls together.

First, the release request must be made using the same instance of the DisplayRequest you used to make the original request to keep the display active. If you don’t follow this rule, RequestRelease() will throw an exception.

Second, the RequestRelease() call cannot be made before a RequestActive() call is made on the same DisplayRequest instance. It will throw an exception if you do.

//make request to put in active state _displayRequest.RequestActive(); }

public void ReleaseDisplay() { //must be same instance, so quit if it doesn't exist if (_displayRequest == null) return;

//undo the request _displayRequest.RequestRelease(); }

It is generally good practice to be mindful of resources and release the display request if you no longer need it. For instance, if you have written a custom video player, you should release the display active request whenever the player pauses, ends, or encounters an error. You can always make another call to RequestActive() when the video player starts again or gets past the error.

Automatic request handling

Without any additional coding, though, your RequestActive() call will also be deactivated when your app no longer has the focus—in other words, when your app goes into a suspended state. On Windows Phone mobile and on a Windows 10 PC or Surface Pro in Tablet mode, “your app no longer having focus” means whenever your app is no longer in the foreground (snapped apps still count as being in the foreground, by the way). On a Windows 10 PC in desktop mode, however, it will mean whenever your app is minimized. In desktop mode, note that even when another app window covers up your app window, your app is still considered by the UWP app lifecycle to be running in the foreground.

The really cool thing is that when your app comes back into the foreground or gets de-minimized, the RequestActive() call will automatically get reactivated. You don’t have to do a thing!

This also means that if another app happens to make a request to keep the display active, it cannot hijack the behavior of every other app on the same device. The request is only good as long as the user is working with that app. Once the app is dismissed or minimized, Windows 10 goes back to its regular power conservation habits, even if the app forgets to call RequestRelease().

Finally, when your app is terminated, all remaining display active requests are automatically cleaned up for you.

Request counting

RequestActive() calls are cumulative. This means that, depending on the architecture of your app, it is possible to make multiple calls to it. Unfortunately, for every call to RequestActive(), you have to make an identical number of calls to RequestRelease() before the display is allowed to function normally again.

One way to manage this is to maintain a tally of the number of times RequestActive() gets invoked.

Then for each call to the sample ActivateDisplay() method above, you also increment the _requestCount field by one. For each call to ReleaseDisplay() above, on the other hand, subtract one from _requestCount.

_displayRequest.RequestActive(); _requestCount++;

This will help you track how many calls need to be released when your app no longer needs to prevent the lock screen from closing. It will also help you avoid calling ReleaseDisplay() too many times and generating an exception. Bear in mind that your app may not require this level of complexity. It largely depends on how your app is architected and how many code paths end up leading to an active display request.

Don’t manage lifecycle events yourself

You may encounter recommendations on the internet to release your display active request when your app is suspended and create a new one when the app resumes. This pseudo-pattern is problematic since it conflicts with the automatic deactivation and reactivation of display requests by the OS when an app moves out of the foreground.

As a general rule, you should allow the automatic behavior, discussed earlier in this post, to manage this for you.

Wrapping up

One day soon, we may have sensors on our devices to let us know if people are reading or watching a movie. Until that day, however, we have the DisplayRequest class to help us let the operating system know what our app users are doing. Using the DisplayRequest class can be as easy or as complicated as you need it to be. It works great out of the box, but also lends itself to sophisticated architectural patterns should the need arise.