Search code examples
c#geolocationsignalrwindows-10-universalwindows-10-mobile

How to still have my app run when it is suspended because of lock screen and then wake the device


I have a Windows UWP app, targeting Windows 10 Mobile for the most part. This application monitors the user's foot traffic and when they are in or out of defined geofences. I then have a web back end that uses SignalR to send position data to/from the device.

The issue is with the lock screen. Let's say that the app is started and running but the user locks the device OR the setting option for timeout to lock the screen expires and the device locks. You could hit power, swipe to unlock and see that the app is still running. However, during the time it is locked, I assume that the app is suspended?

So, I am wondering first of all, what happens to my location updates while suspended? I use these to send the position update via SignalR to my hub but also check if they are in/out of a geofence. I am doing something like this:

_geolocator = new Geolocator { ReportInterval = 0, DesiredAccuracyInMeters = 10, MovementThreshold = 4};

// Subscribe to PositionChanged event to get updated tracking positions
_geolocator.PositionChanged += OnPositionChanged;

// Subscribe to StatusChanged event to get updates of location status changes
_geolocator.StatusChanged += OnStatusChanged;

I assume that when the lock screen has taken over and my app is suspended, I will no longer get my OnPositionChanged events? How is this handled with other things like turn by turn navigation where it will still track your location even if the app is suspended or the lock screen is on?

Also, second question is what to do with the SignalR connection? I would love to still be able to push out my location updates when the OnPositionChanged event fires like I do when the app is not suspended. Can I also do that?

I have read about the background tasks but it seems these only run at 15 minute intervals (unless I misunderstood and this is configurable). For my application, 15 minutes is far too long. The most I would want is 30 seconds or 1 minute.

By the way, yes I understand that all of this has serious implications on battery life. Let's assume that I am not concerned about battery life for this.

Thanks!


Solution

  • The issue is with the lock screen. Let's say that the app is started and running but the user locks the device OR the setting option for timeout to lock the screen expires and the device locks. You could hit power, swipe to unlock and see that the app is still running. However, during the time it is locked, I assume that the app is suspended?

    When you minimizes an app Windows waits a few seconds to see whether the user will switch back to it. If you do not switch back within this time window, and no extended execution, background task, or activity sponsored execution is active, Windows suspends the app. An app is also suspended when the lock screen appears as long as no extended execution session, etc. is active in that app. For more detail you could refer to Windows 10 universal Windows platform (UWP) app lifecycle.

    I assume that when the lock screen has taken over and my app is suspended, I will no longer get my OnPositionChanged events? How is this handled with other things like turn by turn navigation where it will still track your location even if the app is suspended or the lock screen is on?

    For your requirement, you could run your app while minimized with ExtendedExecutionReason.LocationTracking. For example, if you want to realize turn by turn navigation, you could refer to the following code.

    Specify ExtendedExecutionReason.LocationTracking when you create an ExtendedExecutionSession if your app needs to regularly log the location from the GeoLocator. Apps for fitness tracking and navigation that need to regularly monitor the user's location and should use this reason.

    For more detail you could refer to Track the user's location and App Lifecycle - Keep Apps Alive with Background Tasks and Extended Execution.

    private async void StartTbTNavigationSession()
    {
      using (var session = new ExtendedExecutionSession())
      {
        session.Reason = ExtendedExecutionReason.LocationTracking;
        session.Description = "Turn By Turn Navigation";
        session.Revoked += session_Revoked;
        var result = await session.RequestExtensionAsync();
        if (result == ExtendedExecutionResult.Denied
        {
          ShowUserWarning("Background location tracking not available");
        }
        // Do Navigation
        var completionTime = await DoNavigationSessionAsync(session);
      }
    }