Skip to content

Commit c48d5a9

Browse files
authored
Permissions (BT & WiFi): don't add AccessFineLocation to required permissions if NeverForLocation flag is present (#20874)
* otherwise the permission-status will be 'denied' if AccessFineLocation is in the manifest, but denied at runtime (even if it is not strictly required)
1 parent 10bfa7b commit c48d5a9

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

src/Essentials/src/Permissions/Permissions.android.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ public static bool IsDeclaredInManifest(string permission)
2424
return requestedPermissions?.Any(r => r.Equals(permission, StringComparison.OrdinalIgnoreCase)) ?? false;
2525
}
2626

27+
private static bool HasFlagInManifest(string permission, RequestedPermission flag)
28+
{
29+
var context = Application.Context;
30+
#pragma warning disable CS0618, CA1416, CA1422 // Deprecated in API 33: https://developer.android.com/reference/android/content/pm/PackageManager#getPackageInfo(java.lang.String,%20int)
31+
var packageInfo = context.PackageManager.GetPackageInfo(context.PackageName, PackageInfoFlags.Permissions);
32+
#pragma warning restore CS0618, CA1416, CA1422
33+
var requestedPermissions = packageInfo?.RequestedPermissions;
34+
var requestedPermissionsFlags = packageInfo?.RequestedPermissionsFlags;
35+
36+
for (int i=0; i<requestedPermissions.Count; i++)
37+
{
38+
if (requestedPermissions[i].Equals(permission, StringComparison.OrdinalIgnoreCase))
39+
return (requestedPermissionsFlags[i] & (int)flag) != 0;
40+
}
41+
42+
return false;
43+
}
44+
2745
internal static void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
2846
=> BasePlatformPermission.OnRequestPermissionsResult(requestCode, permissions, grantResults);
2947

@@ -204,8 +222,7 @@ public override (string androidPermission, bool isRuntime)[] RequiredPermissions
204222
var permissions = new List<(string, bool)>();
205223

206224
// When targeting Android 11 or lower, AccessFineLocation is required for Bluetooth.
207-
// For Android 12 and above, it is optional.
208-
if (Application.Context.ApplicationInfo.TargetSdkVersion <= BuildVersionCodes.R || IsDeclaredInManifest(Manifest.Permission.AccessFineLocation))
225+
if (Application.Context.ApplicationInfo.TargetSdkVersion <= BuildVersionCodes.R)
209226
permissions.Add((Manifest.Permission.AccessFineLocation, true));
210227

211228
#if __ANDROID_31__
@@ -218,6 +235,9 @@ public override (string androidPermission, bool isRuntime)[] RequiredPermissions
218235
permissions.Add((Manifest.Permission.BluetoothConnect, true));
219236
if (IsDeclaredInManifest(Manifest.Permission.BluetoothAdvertise))
220237
permissions.Add((Manifest.Permission.BluetoothAdvertise, true));
238+
// for Android 12 and above, AccessFineLocation is optional
239+
if (IsDeclaredInManifest(Manifest.Permission.AccessFineLocation) && !HasFlagInManifest(Manifest.Permission.BluetoothScan, RequestedPermission.NeverForLocation))
240+
permissions.Add((Manifest.Permission.AccessFineLocation, true));
221241
}
222242
#endif
223243

@@ -365,8 +385,7 @@ public override (string androidPermission, bool isRuntime)[] RequiredPermissions
365385
{
366386
var permissions = new List<(string, bool)>();
367387
// When targeting Android 12 or lower, AccessFineLocation is required for several WiFi APIs.
368-
// For Android 13 and above, it is optional.
369-
if (Application.Context.ApplicationInfo.TargetSdkVersion < BuildVersionCodes.Tiramisu || IsDeclaredInManifest(Manifest.Permission.AccessFineLocation))
388+
if (Application.Context.ApplicationInfo.TargetSdkVersion < BuildVersionCodes.Tiramisu)
370389
permissions.Add((Manifest.Permission.AccessFineLocation, true));
371390

372391
#if __ANDROID_33__
@@ -375,6 +394,9 @@ public override (string androidPermission, bool isRuntime)[] RequiredPermissions
375394
// new runtime permission on Android 13
376395
if (IsDeclaredInManifest(Manifest.Permission.NearbyWifiDevices))
377396
permissions.Add((Manifest.Permission.NearbyWifiDevices, true));
397+
// for Android 13 and above, AccessFineLocation is optional
398+
if (IsDeclaredInManifest(Manifest.Permission.AccessFineLocation) && !HasFlagInManifest(Manifest.Permission.NearbyWifiDevices, RequestedPermission.NeverForLocation))
399+
permissions.Add((Manifest.Permission.AccessFineLocation, true));
378400
}
379401
#endif
380402

0 commit comments

Comments
 (0)