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
Create a new Xamarin.Android solution
Add the latest Xamarin.Essentials (1.7.3).
Start a foreground service using
[Service(ForegroundServiceType = global::Android.Content.PM.ForegroundService.TypeLocation)]
Wire up a button that will request the user's permission for LocationAlways
Wire up another button that will be used to retrieve the user's location
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" />
Wire up the first button and click with the following request for location permission:
await Permissions.RequestAsync<Permissions.LocationAlways>();
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 filevar request = new GeolocationRequest(GeolocationAccuracy.High, TimeSpan.FromSeconds(10));_cts = new CancellationTokenSource();var location = await Geolocation.GetLocationAsync(request, _cts.Token);
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
Version with issue: Xamarin.Essentials 1.7.3
Last known good version:
IDE: VS 2019 (16.11.11)
Platform Target Frameworks:
Android: 12
Nuget Packages: Xamarin.Essentials 1.7.3
Affected Devices: Google Pixel 4a running Android 12
Set the following permissions
Settings -> Apps -> -> Battery -> Unrestricted
Settings -> Device and battery assistance -> Battery -> Power saving -> off
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
[Service(ForegroundServiceType = global::Android.Content.PM.ForegroundService.TypeLocation)]
<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" />
await Permissions.RequestAsync<Permissions.LocationAlways>();
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);
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