From e8ce50da15811b36dea3638b90a3e7e8123f6c71 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 2 May 2022 15:24:37 -0400 Subject: [PATCH] Fix #1999 - checkasync should return restricted for locationinuse when only coarse is granted --- .../Permissions/Permissions.android.cs | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/Xamarin.Essentials/Permissions/Permissions.android.cs b/Xamarin.Essentials/Permissions/Permissions.android.cs index e80105ae7..a8c0ed99b 100644 --- a/Xamarin.Essentials/Permissions/Permissions.android.cs +++ b/Xamarin.Essentials/Permissions/Permissions.android.cs @@ -57,28 +57,13 @@ public override Task CheckStatusAsync() if (RequiredPermissions == null || RequiredPermissions.Length <= 0) return Task.FromResult(PermissionStatus.Granted); - var context = Platform.AppContext; - var targetsMOrHigher = context.ApplicationInfo.TargetSdkVersion >= BuildVersionCodes.M; - foreach (var (androidPermission, isRuntime) in RequiredPermissions) { var ap = androidPermission; if (!IsDeclaredInManifest(ap)) throw new PermissionException($"You need to declare using the permission: `{androidPermission}` in your AndroidManifest.xml"); - var status = PermissionStatus.Granted; - - if (targetsMOrHigher) - { - if (ContextCompat.CheckSelfPermission(context, androidPermission) != Permission.Granted) - status = PermissionStatus.Denied; - } - else - { - if (PermissionChecker.CheckSelfPermission(context, androidPermission) != PermissionChecker.PermissionGranted) - status = PermissionStatus.Denied; - } - + var status = DoCheck(ap); if (status != PermissionStatus.Granted) return Task.FromResult(PermissionStatus.Denied); } @@ -107,6 +92,38 @@ public override async Task RequestAsync() return PermissionStatus.Granted; } + protected virtual PermissionStatus DoCheck(string androidPermission) + { + var context = Platform.AppContext; + var targetsMOrHigher = context.ApplicationInfo.TargetSdkVersion >= BuildVersionCodes.M; + + if (!IsDeclaredInManifest(androidPermission)) + throw new PermissionException($"You need to declare using the permission: `{androidPermission}` in your AndroidManifest.xml"); + + var status = PermissionStatus.Granted; + + if (targetsMOrHigher) + { + status = ContextCompat.CheckSelfPermission(context, androidPermission) switch + { + Permission.Granted => PermissionStatus.Granted, + Permission.Denied => PermissionStatus.Denied, + _ => PermissionStatus.Unknown + }; + } + else + { + status = PermissionChecker.CheckSelfPermission(context, androidPermission) switch + { + PermissionChecker.PermissionGranted => PermissionStatus.Granted, + PermissionChecker.PermissionDenied => PermissionStatus.Denied, + PermissionChecker.PermissionDeniedAppOp => PermissionStatus.Denied, + _ => PermissionStatus.Unknown + }; + } + return status; + } + protected virtual async Task DoRequest(string[] permissions) { TaskCompletionSource tcs; @@ -233,6 +250,17 @@ public override (string androidPermission, bool isRuntime)[] RequiredPermissions (Manifest.Permission.AccessFineLocation, true) }; + public override Task CheckStatusAsync() + { + if (DoCheck(Manifest.Permission.AccessFineLocation) == PermissionStatus.Granted) + return Task.FromResult(PermissionStatus.Granted); + + if (DoCheck(Manifest.Permission.AccessCoarseLocation) == PermissionStatus.Granted) + return Task.FromResult(PermissionStatus.Restricted); + + return Task.FromResult(PermissionStatus.Denied); + } + public override async Task RequestAsync() { // Check status before requesting first