Windows Phone 7: how to reset the idle detection countdown

Windows Phone 7 like every other phone OS turns off the screen after a period of inactivity. This is not a problem most of the time because any user activity (namely finger interactions on the screen) resets the countdown, so if you are using an application the screen saver will not get in the way. However there are some particular cases where it is useful to disable the idle detection, for example in games or apps that require long reading (or watching). In that case you can completely disable idle detection:

PhoneApplicationService.Current.UserIdleDetectionMode =
    IdleDetectionMode.Disabled;

Keep in mind that this disables the “screen saver” at all, so be careful because you could drain the poor user’s battery if you do it without valid reason.

There is another more interesting case, though: suppose your app uses the accelerometer as its main user input. In this case there won’t be any user activity to trigger a countdown reset, but disabling it at all also doesn’t look like the best idea (what if the user puts the phone on the table to go grab a beer?).

The best in this case would be to reset the count-down when a movement is detected, i.e. treating accelerometer events like screen user input. How to do this?

The answer is extremely simple: you can just disable the IdleDetection and re-enable it again. This will reset the count-down. One little caveat: you cannot re-enable it immediately after having disabled it, the OS is smart enough not to be fooled and will ignore your two commands. You’ll have to wait a short while before re-enabling idle detection.

Here is an example: when I get a new reading from the accelerometer (I’m using the AccelerometerHelper) I check if there has been a large enough movement and in that case I disable the idle detection. Otherwise I enable it –this effectively resets the countdown every time the movement goes above a given threshold. Keep in mind that the accelerometer fires 50 times per second, that’s why I used a bool field to avoid unnecessary calls to the system setting. I’m not sure this prevents an actual performance loss, but it would be worth it to experiment and measure a little if you are using this technique in your apps.

double _currentValue;
bool _screenSaverEnabled = true;

private void OnAccelerometerHelperReadingChanged(object sender, AccelerometerHelperReadingEventArgs e)
{
    Dispatcher.BeginInvoke(() =>
        {
            // you'll have something more useful in your app
            computedValue = e.OptimallyFilteredAcceleration.X;

            var delta = Math.Abs(computedValue - _currentValue);
            if (_screenSaverEnabled)
            {
                if (delta > SOME_ARBITRARY_THRESOLD)
                {
                    _screenSaverEnabled = false;
                    PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
                    Debug.WriteLine("Screen saver disabled");
                }
            }
            else
            {
                _screenSaverEnabled = true;
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Enabled;
                Debug.WriteLine("Screen saver enabled");
            }
            _currentValue = computedValue;
        }
    );
}

Happy coding!