2

I'm struggling to get extended execution session to work for my Windows Universal app.

What I'm trying to achieve is the following scenario. The user wants to connect the phone with a device via Bluetooth. Currently, whenever the screen turns off or an incoming call comes or the user minimizes the app, the connection fails and we restart it on resume. I'd like to enable extended execution for this in-progress connection, such that the app continues the work even when minimized (suspended).

I've figured I need the ExtendedExecutionReason.Unspecified, as it should allow my app to run up to 10 minutes in the suspended state (which is more than enough for my purpose). However, connection always seems to fail on suspending (and I get revoked with ExtendedExecutionRevokedReason.SystemPolicy when I try to alter the state of my app from the debugger using the Application Lifecycle dropdown of VS). I have enabled all battery and background permissions for my app, but still no good.

My code is roughly as follows:

        ... (on begin connection)
        ClearExtendedExcecution();

        DisplayRequest dr = new DisplayRequest();
        var newSession = new ExtendedExecutionSession
        {
            Reason = ExtendedExecutionReason.Unspecified,
            Description = "Pair device"
        };
        newSession.Revoked += SessionRevoked;
        ExtendedExecutionResult result = await newSession.RequestExtensionAsync();

        dr.RequestActive();
        try
        {
            switch (result)
            {
                case ExtendedExecutionResult.Allowed:
                    m_extendedExecutionSession = newSession;
                    // DO WORK HERE
                    await ConnectDeviceAsync(token);
                    break;
                default:
                case ExtendedExecutionResult.Denied:
                    // fallback to request screen active if extended execution fails, but still do work
                    newSession.Dispose();
                    await ConnectDeviceAsync(token);
                    break;
            }
        }
        finally
        {
            dr.RequestRelease();
            ClearExtendedExcecution();
        }
        ... 


    private async void SessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
    {
        await CoreApplication.MainView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            switch (args.Reason)
            {
                case ExtendedExecutionRevokedReason.Resumed:
                    Logger.Debug("Extended execution revoked due to returning to foreground.");
                    break;

                case ExtendedExecutionRevokedReason.SystemPolicy:
                    Logger.Debug("Extended execution revoked due to system policy.");
                    break;
            }
        });
    }

    private void ClearExtendedExcecution()
    {
        if (m_extendedExecutionSession == null)
        {
            return;
        }

        m_extendedExecutionSession.Revoked -= SessionRevoked;
        m_extendedExecutionSession.Dispose();
        m_extendedExecutionSession = null;
    }

Any tips on what I am doing wrongly, how exactly the Extended Execution Session is meant to be used or how to debug the lifecycle of the app (without getting the system policy revocation) would be greatly appreciated. Thanks!

barca_d
  • 1,031
  • 2
  • 13
  • 30
  • Please try to modify the ExtendedExecutionReason.Unspecified to ExtendedExecutionReason.SavingData. – Jayden May 25 '16 at 09:37

2 Answers2

7

In this case "Suspend" lifecycle event in VS simulates suspension due to low resources, so that's why you get as a reason "SystemPolicy".

If you run your application without attached debugger, you minimize it (desktop) or switch to another application (phone) the execution will continue, however (!) when you resume your application the session is revoked with "Resumed" reason and you have to start your session again by calling RequestExtensionAsync() method.

This technique ensures that your execution will be active as long as you need.

Tom Shane
  • 694
  • 7
  • 18
  • Yes, thanks for the explanation. I got this figured out by my own a couple of time ago. I was confused because of the resources I had found related to this problem. Most of the samples used extended execution for lengthening the OnSuspended callback such that it allowed them to save some state. I actually needed it for exchanging messages back and forth via BLE. In the end I used toasts and logging to figure out what was exactly happening in relation to this. Basically, on resume revocation, you need to request a new session. You also need to be careful about how you dispose of old sessions – barca_d Jun 11 '16 at 09:58
0

Here is the tutorial on Extended Execution: https://learn.microsoft.com/en-us/windows/uwp/launch-resume/run-minimized-with-extended-execution

Here is the set of samples for Extended Execution: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/ExtendedExecution

You are correct, it is best to use Unspecified Extended Execution or Location Tracking while your app is in the running state and not a Saving Data while in the Suspending state. For your specific scenario it sounds like you are trying to continue communication with a Bluetooth device from a Windows Phone. Depending on whether the Bluetooth device is BLE or earlier, a GattCharacteristicNotificationTrigger or RfCommConnectionTrigger may be better options. They do not require your app to be constantly running in the background and instead wake your app during peripheral communication. Kiran's overview of the different types of Bluetooth triggers from last year's Build conference is informative and available here: https://channel9.msdn.com/Events/Build/2016/P460

chcortes
  • 116
  • 4