-
Notifications
You must be signed in to change notification settings - Fork 2.9k
No clean way to stop the Android foreground service in background location demo #120
Description
Sample
https://github.com/xamarin/mobile-samples/tree/main/BackgroundLocationDemo
Description
In the background location demo, when the app is swiped away, the OnDestroy
is called as expected, and this method then proceeds to clean up the foreground service. Ostensibly the service is no longer running, as indicated by the running services in the developer section of the device. However, the visual Studio debugger stays attached indicating that the app is still running, and in list of apps on the device, the force close button is enabled for the app, also indicating running. Moreover, when the app is restarted on the device, the UI subscribes a second event handler to the foreground service, resulting in duplicate events in the UI after each location change. This suggests that the service instance has not been cleaned between the app executions.
The issue is that I have not been able to determine a clean way to stop the foreground service in the sample programmatically. All the documentation and related discussion would seem to suggest that this should be possible.
Now, in principle the described behavior would be fine, as the foreground service seems to stop providing the location updates when the app is closed, thus resulting in no wasted cycles when the app is not running. However, an existing and running foreground service should be handled in the main activity OnCreate
when the application starts, or we risk creating duplicate resources, or at least setting unneeded event subscriptions.
This behavior happens both on device and emulator; and is not unique to the background location demo, the same behavior is present in a similar foreground service with no actual functionality.
I have attempted to clean up the foreground service with the following methods:
- unsubscribed -= from all events
- unbound the service with
Application.Context.UnbindService
- deleted the notification channel with
DeleteNotificationChannel
on notification manager - called
RemoveUpdates
onLocationManager
- cancelled the
Task
used to start the location service - called
StopService
inOnDestroy
- called
StopSelf
inOnDestroy
- called
StopForeground
withStopForegroundFlags.Remove
andStopSelf
inOnTaskRemoved
(OnTaskRemoved
onLocationService
is being executed as expected) - called
Dispose
on all disposable objects (binder, location manager, location service) - although disposing the location service results in aNotSupportedException
(Unable to activate instance from native handle) soon after the disposal, crashing the application (and finally terminating the process, but arguably not the way it should).
I may have not gotten the order of operations right, but it seems that I have exhausted most of the avenues available. Perhaps someone with more detailed knowledge of Xamarin resource management could modify the sample project in a way that cleanly shutdowns the service.
I am opening the ticket here as the sample may just be missing something, and if we are not able to find a set of steps to cleanly shutdown the foreground service, we may want to open another on xamarin-android or Xamarin.Forms.
Alternatively, if not cleaning the foreground service is ok (it still seems strange to have to terminate the debugging session manually) we should at least have an example where the OnCreate
cleanly handles an existing foreground service.
Steps to Reproduce
- Run the background location demo from Visual Studio with debugger attached, wait for a GPS update on UI
- Swipe the application away
- Run the background location demo from the device or emulator, wait for a GPS update on UI
- Swipe the application away
Expected Behavior
- Debugger stops in VS
- Settings - Developer options - Running Services - Location.Droid: changes from "1 process and 1 service" to "Not Active"
- Settings - Apps - Location.Droid - Force stop: changes from enabled to disabled
- The service is created such that the main activity receives an update request per location change. This can be seen in the logs as follows:
[LocationService] Speed is 0 [LocationService] Accuracy is 61.47781 [LocationService] Bearing is 0 [MainActivity] Foreground updating [LocationService] Latitude is ...
Actual Behavior
- Debugger does not stop in VS
- Settings - Developer options - Running Services - Location.Droid: changes from "1 process and 1 service" to "Not Active"
- Settings - Apps - Location.Droid - Force stop: stays enabled
- The service is created such that the main activity receives a multiple update requests per location change. This can be seen in the logs as follows:
[LocationService] Speed is 0 [LocationService] Accuracy is 61.47781 [LocationService] Bearing is 0 [MainActivity] Foreground updating [MainActivity] Foreground updating [LocationService] Latitude is ...
Information
Microsoft Visual Studio Professional 2019 Version 16.11.2 VisualStudio.16.Release/16.11.2+31624.102
Microsoft .NET Framework Version 4.8.04084
Mono Debugging for Visual Studio 16.10.15 (552afdf)
Xamarin 16.11.000.174 (d16-11@e8f56f1)
Xamarin Designer 16.11.0.17 (remotes/origin/11e0001f0b17269345e80b58fb3adf1ba4efe2cd@11e0001f0)
Xamarin Templates 16.10.5 (355b57a)
Xamarin.Android SDK 11.4.0.5 (d16-11/7776c9f)
Xamarin.Android Reference Assemblies and MSBuild support. Mono: c633fe9 Java.Interop: xamarin/java.interop/d16-11@48766c0 ProGuard: Guardsquare/proguard@912d149 SQLite: xamarin/sqlite@85460d3 Xamarin.Android Tools: xamarin/xamarin-android-tools/d16-11@683f375
Android 11.0 (R) / API 30
Xamarin.Android.Support.x 28.0.0.3 -or- Xamarin.Forms 5.0.0.2083 and Xamarin.Essentials 1.7.0
Samsung SM-T725 (Android 11.0 - API 30)
Workaround
As a workaround, per https://stackoverflow.com/a/18450763, we may use Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
which does not allow a controlled cleanup of resources, but may be fine if executed as the last step on the OnDestroy
of the main activity.