Skip to content

Commit

Permalink
Fix permissions for GPS and checks for core current states
Browse files Browse the repository at this point in the history
  • Loading branch information
aritchie committed Nov 29, 2023
1 parent de4a956 commit 9d09a0a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 18 deletions.
63 changes: 52 additions & 11 deletions src/Shiny.Core/Platforms/Android/AndroidPlatform.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Disposables;
Expand All @@ -14,6 +15,8 @@
using AndroidX.Core.Content;
using AndroidX.Core.App;
using Shiny.Hosting;
using Shiny.Stores;
using Shiny.Stores.Impl;

namespace Shiny;

Expand All @@ -22,34 +25,45 @@ public partial class AndroidPlatform : IPlatform,
IAndroidLifecycle.IOnActivityRequestPermissionsResult,
IAndroidLifecycle.IOnActivityResult
{
const string PermissionsKey = nameof(PermissionsKey);
int requestCode;
readonly List<string> requestedPermissions;

static AndroidActivityLifecycle activityLifecycle; // this should never change once installed on the platform
readonly Subject<PermissionRequestResult> permissionSubject = new();
readonly Subject<(int RequestCode, Result Result, Intent Intent)> activityResultSubject = new();

readonly SettingsKeyValueStore store;

public AndroidPlatform()
{
var app = (Application)Application.Context;
activityLifecycle ??= new(app);

this.AppContext = app;
this.AppData = new DirectoryInfo(this.AppContext.FilesDir.AbsolutePath);
this.Cache = new DirectoryInfo(this.AppContext.CacheDir.AbsolutePath);
var publicDir = this.AppContext.GetExternalFilesDir(null);
if (publicDir != null)
this.Public = new DirectoryInfo(publicDir.AbsolutePath);

this.store = new(this, new DefaultSerializer());
this.requestedPermissions = this.store.Get<List<string>>(PermissionsKey) ?? new List<string>();
}

public AccessState GetCurrentPermissionStatus(string androidPermission)
=> ContextCompat.CheckSelfPermission(this.AppContext, androidPermission) switch
{
Permission.Granted => AccessState.Available,
Permission.Denied => AccessState.Denied,
_ => ActivityCompat.ShouldShowRequestPermissionRationale(this.CurrentActivity!, androidPermission)
? AccessState.Unknown
: AccessState.Denied
};
{
var self = ContextCompat.CheckSelfPermission(this.AppContext, androidPermission);
if (self == Permission.Granted)
return AccessState.Available;

if (!this.HasRequestedPermission(androidPermission))
return AccessState.Unknown;

//var showRequest = ActivityCompat.ShouldShowRequestPermissionRationale(this.CurrentActivity!, androidPermission);
//if (showRequest)
// return AccessState.Unknown;

return AccessState.Denied;
}

// lifecycle hooks
public void Handle(Activity activity, int requestCode, string[] permissions, Permission[] grantResults)
Expand Down Expand Up @@ -171,7 +185,7 @@ public IObservable<PermissionRequestResult> RequestPermissions(params string[] a
{
//if (this.Status == PlatformState.Background)
// throw new ApplicationException("You cannot make permission requests while your application is in the background. Please call RequestAccess in the Shiny library you are using while your app is in the foreground so your user can respond. You are getting this message because your user has either not granted these permissions or has removed them.");

this.SetRequestedPermissions(androidPermissions);
var current = Interlocked.Increment(ref this.requestCode);
comp.Add(this
.permissionSubject
Expand Down Expand Up @@ -199,4 +213,31 @@ public IObservable<PermissionRequestResult> RequestPermissions(params string[] a

return comp;
});

void SetRequestedPermissions(string[] androidPermissions)
{
lock (this.requestedPermissions)
{
var count = this.requestedPermissions.Count;
foreach (var p in androidPermissions)
{
if (!this.requestedPermissions.Contains(p, StringComparer.InvariantCultureIgnoreCase))
this.requestedPermissions.Add(p);
}
if (count != this.requestedPermissions.Count)
this.store.Set(PermissionsKey, this.requestedPermissions);
}
}


bool HasRequestedPermission(string androidPermission)
{
lock (this.requestedPermissions)
{
return this.requestedPermissions.Contains(
androidPermission,
StringComparer.InvariantCultureIgnoreCase
);
}
}
}
1 change: 0 additions & 1 deletion src/Shiny.Core/Platforms/Android/Stores/AndroidKeyStore.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// modified from Xamarin Essentials source
using System;
using System.Security.Cryptography;
using System.Text;
using Android.Content;
using Android.Runtime;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using Android.Content;
using Shiny.Infrastructure;
using Shiny.Reflection;

namespace Shiny.Stores;
Expand Down
16 changes: 12 additions & 4 deletions src/Shiny.Locations/Platforms/Android/AbstractGpsManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;
Expand Down Expand Up @@ -70,11 +71,18 @@ public AndroidGpsRequest? CurrentSettings
public GpsRequest? CurrentListener => this.currentSettings;


// TODO: Implement
public AccessState GetCurrentStatus(GpsRequest request)
{
var ps = this.GetPermissionSet(request);
var states = ps.Select(this.Platform.GetCurrentPermissionStatus).ToList();
if (states.Any(x => x == AccessState.Unknown))
return AccessState.Unknown;

return AccessState.Unknown;
if (states.All(x => x == AccessState.Available))
return AccessState.Available;

// TODO: what if fine is denied but coarse is good? should be restricted
return AccessState.Denied;
}


Expand All @@ -100,8 +108,8 @@ protected virtual List<string> GetPermissionSet(GpsRequest request)
if (OperatingSystemShim.IsAndroidVersionAtLeast(31))
permissionSet.Add(P.ForegroundService);

if (OperatingSystemShim.IsAndroidVersionAtLeast(33))
permissionSet.Add(AndroidPermissions.PostNotifications);
//if (OperatingSystemShim.IsAndroidVersionAtLeast(33))
// permissionSet.Add(AndroidPermissions.PostNotifications);
break;
}
if (requestBg && OperatingSystemShim.IsAndroidVersionAtLeast(29))
Expand Down
3 changes: 2 additions & 1 deletion tests/Shiny.Tests/Shiny.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsVersion)" />
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="MartinCostello.Logging.XUnit" Version="0.3.0" />
<PackageReference Include="Shiny.Xunit.Runners.Maui" Version="1.0.0" />
</ItemGroup>
Expand Down

0 comments on commit 9d09a0a

Please sign in to comment.