xamarin / Essentials

Xamarin.Essentials is no longer supported. Migrate your apps to .NET MAUI, which includes Maui.Essentials.
https://aka.ms/xamarin-upgrade
Other
1.52k stars 505 forks source link

[Bug] [Android12] Geolocation does not return location in background when ONLY approximate location is granted #2024

Open rubverma opened 2 years ago

rubverma commented 2 years ago

Description

When targeting Android 12 on a device running Android 12, prompting the user for location permission access has the option for both precise and approximate. If the user selects 'approximate' & 'All the time' then in code Geolocation.GetLocationAsync() is not returning location coordinates. I have a foreground Service started and Geolocation.GetLocationAsync() is called when the app is in a background state (When the user is not actually using the app).

Steps to Reproduce

  1. Create a new Xamarin.Android solution
  2. Add the latest Xamarin.Essentials (1.7.3).
  3. Start a foreground service using [Service(ForegroundServiceType = global::Android.Content.PM.ForegroundService.TypeLocation)]
  4. Wire up a button that will request the user's permission for LocationAlways
  5. Wire up another button that will be used to retrieve the user's location
  6. Update the AndroidManifest with the following permissions and features: <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-feature android:name="android.hardware.location" android:required="false" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <uses-feature android:name="android.hardware.location.network" android:required="false" />
  7. Wire up the first button and click with the following request for location permission: await Permissions.RequestAsync<Permissions.LocationAlways>();
  8. Wire up the second button and click with the following user location request: private CancellationTokenSource _cts;//this should be a field at the class level for the code behind file var request = new GeolocationRequest(GeolocationAccuracy.High, TimeSpan.FromSeconds(10)); _cts = new CancellationTokenSource(); var location = await Geolocation.GetLocationAsync(request, _cts.Token);
  9. Add a 2s delay in the second button click before calling the location method, to simulate getting the location in the background state (for the actual use case GetLocationAsync method is getting called from the BLE device) await Task.Delay(2000);

Expected Behavior

Upon pressing the first button the user will be prompted to choose between precise or approximate location (select approximate) then the app location permission setting page will be displayed (select All the time). Upon pressing the second button and placing the app in the background the user's location should be retrieved.

Actual Behavior

Upon pressing the first button the user will be prompted to choose between precise or approximate location (select approximate) then the app location permission setting page will be displayed (select All the time). After pressing the second button and placing the app in the background, location information is not received. It is not even throwing an error. Location is available once I'll bring the app to the foreground.

Basic Information

gpsaliola commented 2 years ago

Try this (for Android 12):

  1. Add in your manifest:
  2. Set the following permissions Settings -> Apps -> -> Battery -> Unrestricted Settings -> Device and battery assistance -> Battery -> Power saving -> off