From 900fc2a35aa5eec21a8f2d34739c89a0ce3710e0 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Thu, 7 Mar 2024 11:23:21 -0800 Subject: [PATCH] Add `PermissionsUtil#requestPermissions(...)` to provide the ability to request multiple permissions at a time Fix https://github.com/GodotVR/godot_openxr_vendors/issues/101 --- .../godot/utils/PermissionsUtil.java | 132 ++++++++++++------ 1 file changed, 86 insertions(+), 46 deletions(-) diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index 737b4ac20bda..9a6b6d5037ff 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -41,12 +41,16 @@ import android.os.Build; import android.os.Environment; import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -67,12 +71,74 @@ private PermissionsUtil() { } /** - * Request a dangerous permission. name must be specified in this - * @param permissionName the name of the requested permission. + * Request a list of dangerous permissions. The requested permissions must be included in the app's AndroidManifest + * @param permissions list of the permissions to request. + * @param activity the caller activity for this method. + * @return true/false. "true" if permissions are already granted, "false" if a permissions request was dispatched. + */ + public static boolean requestPermissions(Activity activity, List permissions) { + if (activity == null) { + return false; + } + + if (permissions == null || permissions.isEmpty()) { + return true; + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + // Not necessary, asked on install already + return true; + } + + Set requestedPermissions = new HashSet<>(); + for (String permission : permissions) { + try { + if (permission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) { + Log.d(TAG, "Requesting permission " + permission); + try { + Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); + intent.setData(Uri.parse(String.format("package:%s", activity.getPackageName()))); + activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE); + } catch (Exception ignored) { + Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); + activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE); + } + } + } else { + PermissionInfo permissionInfo = getPermissionInfo(activity, permission); + int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel; + if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + Log.d(TAG, "Requesting permission " + permission); + requestedPermissions.add(permission); + } + } + } catch (PackageManager.NameNotFoundException e) { + // Skip this permission and continue. + Log.w(TAG, "Unable to identify permission " + permission, e); + } + } + + if (requestedPermissions.isEmpty()) { + // If list is empty, all of dangerous permissions were granted. + return true; + } + + activity.requestPermissions(requestedPermissions.toArray(new String[0]), REQUEST_ALL_PERMISSION_REQ_CODE); + return true; + } + + /** + * Request a dangerous permission. The requested permission must be included in the app's AndroidManifest + * @param permissionName the name of the permission to request. * @param activity the caller activity for this method. * @return true/false. "true" if permission is already granted, "false" if a permission request was dispatched. */ public static boolean requestPermission(String permissionName, Activity activity) { + if (activity == null || TextUtils.isEmpty(permissionName)) { + return false; + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // Not necessary, asked on install already return true; @@ -137,11 +203,15 @@ public static boolean requestManifestPermissions(Activity activity) { * @return true/false. "true" if all permissions were already granted, returns "false" if permissions requests were dispatched. */ public static boolean requestManifestPermissions(Activity activity, @Nullable Set excludes) { + if (activity == null) { + return false; + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } - String[] manifestPermissions; + List manifestPermissions; try { manifestPermissions = getManifestPermissions(activity); } catch (PackageManager.NameNotFoundException e) { @@ -149,48 +219,17 @@ public static boolean requestManifestPermissions(Activity activity, @Nullable Se return false; } - if (manifestPermissions.length == 0) + if (manifestPermissions.isEmpty()) { return true; - - List requestedPermissions = new ArrayList<>(); - for (String manifestPermission : manifestPermissions) { - if (excludes != null && excludes.contains(manifestPermission)) { - continue; - } - try { - if (manifestPermission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) { - Log.d(TAG, "Requesting permission " + manifestPermission); - try { - Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); - intent.setData(Uri.parse(String.format("package:%s", activity.getPackageName()))); - activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE); - } catch (Exception ignored) { - Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); - activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE); - } - } - } else { - PermissionInfo permissionInfo = getPermissionInfo(activity, manifestPermission); - int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel; - if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, manifestPermission) != PackageManager.PERMISSION_GRANTED) { - Log.d(TAG, "Requesting permission " + manifestPermission); - requestedPermissions.add(manifestPermission); - } - } - } catch (PackageManager.NameNotFoundException e) { - // Skip this permission and continue. - Log.w(TAG, "Unable to identify permission " + manifestPermission, e); - } } - if (requestedPermissions.isEmpty()) { - // If list is empty, all of dangerous permissions were granted. - return true; + if (excludes != null && !excludes.isEmpty()) { + for (String excludedPermission : excludes) { + manifestPermissions.remove(excludedPermission); + } } - activity.requestPermissions(requestedPermissions.toArray(new String[0]), REQUEST_ALL_PERMISSION_REQ_CODE); - return false; + return requestPermissions(activity, manifestPermissions); } /** @@ -199,15 +238,16 @@ public static boolean requestManifestPermissions(Activity activity, @Nullable Se * @return granted permissions list */ public static String[] getGrantedPermissions(Context context) { - String[] manifestPermissions; + List manifestPermissions; try { manifestPermissions = getManifestPermissions(context); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return new String[0]; } - if (manifestPermissions.length == 0) - return manifestPermissions; + if (manifestPermissions.isEmpty()) { + return new String[0]; + } List grantedPermissions = new ArrayList<>(); for (String manifestPermission : manifestPermissions) { @@ -256,12 +296,12 @@ public static boolean hasManifestPermission(Context context, String permission) * @return manifest permissions list * @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found. */ - private static String[] getManifestPermissions(Context context) throws PackageManager.NameNotFoundException { + public static List getManifestPermissions(Context context) throws PackageManager.NameNotFoundException { PackageManager packageManager = context.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS); if (packageInfo.requestedPermissions == null) - return new String[0]; - return packageInfo.requestedPermissions; + return Collections.emptyList(); + return Arrays.asList(packageInfo.requestedPermissions); } /**