Search code examples
androidxamarin.formsgeolocationforeground-servicexamarin.essentials

Xamarin Forms Getting foreground service location updates with CrossGeolocator


I am using the CrossGeolocator plugin to subscribe to location updates in a Xamarin Forms application, for Android (for iOS, location updates will continue even when the app is in the background).

I implemented a Foreground Service so that I can continue to get location even while the app goes to the background.

As I understand, I should be able to get location updates if I listen to them in a foreground service.

However, I do not get location updates when the app goes the the background.

My StartCommand of my service datasource:

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
    Notification notif = DependencyService.Get<INotification>().ReturnNotif();
    StartForeground(ServiceRunningNotifID, notif);

    CrossGeolocator.Current.StartListeningAsync(TimeSpan.FromSeconds(10), 0, true, new Plugin.Geolocator.Abstractions.ListenerSettings
    {
        ActivityType = ActivityType.Other,
        PauseLocationUpdatesAutomatically = false,
        AllowBackgroundUpdates = true,
        DeferLocationUpdates = false,
        ListenForSignificantChanges = false,
    });

    CrossGeolocator.Current.PositionChanged += PositionChanged;
    CrossGeolocator.Current.PositionError += PositionError;


    return StartCommandResult.Sticky;
}

And events:

private void PositionError(object sender, PositionErrorEventArgs e)
{
    Console.WriteLine($"{e.Error}");
}

private void PositionChanged(object sender, PositionEventArgs e)
{
    Console.WriteLine($"{e.Position.Latitude}, {e.Position.Longitude}");
}

The events only fire when the app is active. The service starts, and the device shows the notification badge that the service is running.

I have assigned the required permissions:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.LOCATION_HARDWARE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Can anyone shed some light on the implementation? I can provide additional code if required.


Solution

  • I found the solution by adding this:

    ForegroundServiceType = ForegroundService.TypeDataSync | ForegroundService.TypeLocation

    As the Service Attribute in the Foreground Service

    [Service(ForegroundServiceType = ForegroundService.TypeDataSync | ForegroundService.TypeLocation)]
    public class LocationForegroundService : Service
    {
        ...
    }