Skip to content

Commit

Permalink
Fix auto start of GPS on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
aritchie committed Nov 24, 2023
1 parent a42bac7 commit 8e959a5
Showing 1 changed file with 36 additions and 21 deletions.
57 changes: 36 additions & 21 deletions src/Shiny.Locations/Platforms/Android/AbstractGpsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ public virtual async void Start()
{
try
{
await this.StartListener(this.CurrentSettings).ConfigureAwait(false);
await this.StartListenerInternal(this.CurrentSettings).ConfigureAwait(false);
}
catch (Exception ex)
{
this.logger.LogWarning("Failed to auto-start GPS", ex);
this.logger.LogWarning(ex, "Failed to auto-start GPS");
}
}
}
Expand Down Expand Up @@ -69,16 +69,16 @@ public AndroidGpsRequest? CurrentSettings
public GpsRequest? CurrentListener => this.currentSettings;


// TODO: Implement
public AccessState GetCurrentStatus(GpsRequest request)
{

return AccessState.Unknown;
}



public async Task<AccessState> RequestAccess(GpsRequest request)
protected virtual List<string> GetPermissionSet(GpsRequest request)
{
var status = AccessState.Denied;
var realtime = request.BackgroundMode == GpsBackgroundMode.Realtime;
var requestBg = false;
var permissionSet = new List<string> { P.AccessCoarseLocation };
Expand All @@ -103,8 +103,21 @@ public async Task<AccessState> RequestAccess(GpsRequest request)
permissionSet.Add(AndroidPermissions.PostNotifications);
break;
}
if (requestBg && OperatingSystemShim.IsAndroidVersionAtLeast(29))
permissionSet.Add(P.AccessBackgroundLocation);

return permissionSet;
}

public async Task<AccessState> RequestAccess(GpsRequest request)
{
var permissionSet = this.GetPermissionSet(request);
var status = AccessState.Denied;
var requestBg = permissionSet.Contains(P.AccessBackgroundLocation);

// TODO: test BG permission shouldn't
var result = await this.Platform.RequestPermissions(permissionSet.ToArray()).ToTask();

if (result.IsGranted(P.AccessCoarseLocation))
{
status = AccessState.Available;
Expand All @@ -124,10 +137,6 @@ public async Task<AccessState> RequestAccess(GpsRequest request)

if (permissionSet.Contains(P.ForegroundService) && !result.IsGranted(P.ForegroundService))
return AccessState.NotSetup;

// foreground does not fail - the notification will not show but the service will show up in the task manager as per: https://developer.android.com/develop/ui/views/notifications/notification-permission
if (permissionSet.Contains(AndroidPermissions.PostNotifications) && !result.IsGranted(AndroidPermissions.PostNotifications))
status = AccessState.Restricted; // without post notifications, foreground service will fail
}

//if (this.Platform.GetSystemService<LocationManager>(Context.LocationService)!.IsLocationEnabled)
Expand All @@ -144,17 +153,7 @@ public virtual async Task StartListener(GpsRequest request)
if (this.CurrentListener != null)
throw new InvalidOperationException("There is already a GPS listener running");

request ??= new GpsRequest();
if (request is not AndroidGpsRequest android)
android = new AndroidGpsRequest(request.BackgroundMode, request.Accuracy, request.DistanceFilterMeters);

(await this.RequestAccess(request)).Assert(allowRestricted: true);

if (request.BackgroundMode == GpsBackgroundMode.Realtime && !ShinyGpsService.IsStarted)
this.Platform.StartService(typeof(ShinyGpsService), android.StopForegroundServiceWithTask);

await this.RequestLocationUpdates(request);
this.CurrentSettings = android;
await this.StartListenerInternal(request);
}


Expand All @@ -173,5 +172,21 @@ public virtual async Task StopListener()

public abstract IObservable<GpsReading?> GetLastReading();
protected abstract Task RequestLocationUpdates(GpsRequest request);
protected abstract Task RemoveLocationUpdates();
protected abstract Task RemoveLocationUpdates();


protected async Task StartListenerInternal(GpsRequest request)
{
request ??= new GpsRequest();
if (request is not AndroidGpsRequest android)
android = new AndroidGpsRequest(request.BackgroundMode, request.Accuracy, request.DistanceFilterMeters);

(await this.RequestAccess(request)).Assert(allowRestricted: true);

if (request.BackgroundMode == GpsBackgroundMode.Realtime && !ShinyGpsService.IsStarted)
this.Platform.StartService(typeof(ShinyGpsService), android.StopForegroundServiceWithTask);

await this.RequestLocationUpdates(request);
this.CurrentSettings = android;
}
}

0 comments on commit 8e959a5

Please sign in to comment.