Selaa lähdekoodia

Updates how the `REQUEST_INSTALL_PACKAGES` permission is handled

- Only request the permission the first time the editor tries to open an apk
- Disable the permission for the HorizonOS build as the HorizonOS store doesn't support it yet
Fredia Huya-Kouadio 7 kuukautta sitten
vanhempi
commit
7ad9d23a1d

+ 1 - 1
platform/android/export/export.cpp

@@ -52,7 +52,7 @@ void register_android_exporter() {
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD));
 
 #ifdef ANDROID_ENABLED
-	EDITOR_DEF_BASIC("export/android/install_exported_apk", true);
+	EDITOR_DEF_BASIC("export/android/install_exported_apk", !OS::get_singleton()->has_feature("horizonos"));
 #else
 	EDITOR_DEF_BASIC("export/android/java_sdk_path", OS::get_singleton()->get_environment("JAVA_HOME"));
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/java_sdk_path", PROPERTY_HINT_GLOBAL_DIR));

+ 3 - 0
platform/android/java/editor/src/horizonos/AndroidManifest.xml

@@ -34,6 +34,9 @@
     <!-- Scene api -->
     <uses-permission android:name="com.oculus.permission.USE_SCENE" />
 
+    <!-- Temp removal of the 'REQUEST_INSTALL_PACKAGES' permission as it's currently forbidden by the Horizon OS store -->
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" tools:node="remove" />
+
     <application>
 
         <activity

+ 11 - 2
platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt

@@ -130,11 +130,20 @@ abstract class BaseGodotEditor : GodotActivity() {
 	 */
 	@CallSuper
 	protected open fun getExcludedPermissions(): MutableSet<String> {
-		return mutableSetOf(
+		val excludedPermissions = mutableSetOf(
 			// The RECORD_AUDIO permission is requested when the "audio/driver/enable_input" project
 			// setting is enabled.
-			Manifest.permission.RECORD_AUDIO
+			Manifest.permission.RECORD_AUDIO,
 		)
+
+		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+			excludedPermissions.add(
+				// The REQUEST_INSTALL_PACKAGES permission is requested the first time we attempt to
+				// open an apk file.
+				Manifest.permission.REQUEST_INSTALL_PACKAGES,
+			)
+		}
+		return excludedPermissions
 	}
 
 	override fun onCreate(savedInstanceState: Bundle?) {

+ 2 - 1
platform/android/java/lib/src/org/godotengine/godot/Godot.kt

@@ -1039,7 +1039,8 @@ class Godot(private val context: Context) {
 	}
 
 	fun requestPermission(name: String?): Boolean {
-		return requestPermission(name, getActivity())
+		val activity = getActivity() ?: return false
+		return requestPermission(name, activity)
 	}
 
 	fun requestPermissions(): Boolean {

+ 3 - 5
platform/android/java/lib/src/org/godotengine/godot/GodotIO.java

@@ -30,13 +30,12 @@
 
 package org.godotengine.godot;
 
+import org.godotengine.godot.error.Error;
 import org.godotengine.godot.input.GodotEditText;
 
 import android.app.Activity;
-import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Build;
@@ -47,7 +46,6 @@ import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayCutout;
-import android.view.Surface;
 import android.view.WindowInsets;
 
 import androidx.core.content.FileProvider;
@@ -121,10 +119,10 @@ public class GodotIO {
 			}
 
 			activity.startActivity(intent);
-			return 0;
+			return Error.OK.toNativeValue();
 		} catch (Exception e) {
 			Log.e(TAG, "Unable to open uri " + uriString, e);
-			return 1;
+			return Error.FAILED.toNativeValue();
 		}
 	}
 

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/error/Error.kt

@@ -92,7 +92,7 @@ enum class Error(private val description: String) {
 		}
 	}
 
-	internal fun toNativeValue(): Int = this.ordinal
+	fun toNativeValue(): Int = this.ordinal
 
 	override fun toString(): String {
 		return description

+ 32 - 48
platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java

@@ -44,11 +44,13 @@ import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
 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;
@@ -76,11 +78,11 @@ public final class PermissionsUtil {
 	 * @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<String> permissions) {
-		if (activity == null) {
-			return false;
-		}
+	public static boolean requestPermissions(@NonNull Activity activity, List<String> permissions) {
+		return requestPermissions(activity, permissions, REQUEST_ALL_PERMISSION_REQ_CODE);
+	}
 
+	private static boolean requestPermissions(@NonNull Activity activity, List<String> permissions, int requestCode) {
 		if (permissions == null || permissions.isEmpty()) {
 			return true;
 		}
@@ -90,6 +92,7 @@ public final class PermissionsUtil {
 			return true;
 		}
 
+		boolean dispatchedPermissionsRequest = false;
 		Set<String> requestedPermissions = new HashSet<>();
 		for (String permission : permissions) {
 			try {
@@ -104,6 +107,7 @@ public final class PermissionsUtil {
 							Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
 							activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE);
 						}
+						dispatchedPermissionsRequest = true;
 					}
 				} else if (permission.equals(Manifest.permission.REQUEST_INSTALL_PACKAGES)) {
 					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !activity.getPackageManager().canRequestPackageInstalls()) {
@@ -111,6 +115,7 @@ public final class PermissionsUtil {
 							Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
 							intent.setData(Uri.parse(String.format("package:%s", activity.getPackageName())));
 							activity.startActivityForResult(intent, REQUEST_INSTALL_PACKAGES_REQ_CODE);
+							dispatchedPermissionsRequest = true;
 						} catch (Exception e) {
 							Log.e(TAG, "Unable to request permission " + Manifest.permission.REQUEST_INSTALL_PACKAGES);
 						}
@@ -129,13 +134,12 @@ public final class PermissionsUtil {
 			}
 		}
 
-		if (requestedPermissions.isEmpty()) {
-			// If list is empty, all of dangerous permissions were granted.
-			return true;
+		if (!requestedPermissions.isEmpty()) {
+			activity.requestPermissions(requestedPermissions.toArray(new String[0]), requestCode);
+			dispatchedPermissionsRequest = true;
 		}
 
-		activity.requestPermissions(requestedPermissions.toArray(new String[0]), REQUEST_ALL_PERMISSION_REQ_CODE);
-		return false;
+		return !dispatchedPermissionsRequest;
 	}
 
 	/**
@@ -144,57 +148,37 @@ public final class PermissionsUtil {
 	 * @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
+	public static boolean requestPermission(String permissionName, @NonNull Activity activity) {
+		if (TextUtils.isEmpty(permissionName)) {
 			return true;
 		}
 
+		final int requestCode;
+		final String updatedPermissionName;
 		switch (permissionName) {
 			case "RECORD_AUDIO":
-			case Manifest.permission.RECORD_AUDIO:
-				if (ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
-					activity.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, REQUEST_RECORD_AUDIO_PERMISSION);
-					return false;
-				}
-				return true;
+				updatedPermissionName = Manifest.permission.RECORD_AUDIO;
+				requestCode = REQUEST_RECORD_AUDIO_PERMISSION;
+				break;
 
 			case "CAMERA":
-			case Manifest.permission.CAMERA:
-				if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
-					activity.requestPermissions(new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA_PERMISSION);
-					return false;
-				}
-				return true;
+				updatedPermissionName = Manifest.permission.CAMERA;
+				requestCode = REQUEST_CAMERA_PERMISSION;
+				break;
 
 			case "VIBRATE":
-			case Manifest.permission.VIBRATE:
-				if (ContextCompat.checkSelfPermission(activity, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) {
-					activity.requestPermissions(new String[] { Manifest.permission.VIBRATE }, REQUEST_VIBRATE_PERMISSION);
-					return false;
-				}
-				return true;
+				updatedPermissionName = Manifest.permission.VIBRATE;
+				requestCode = REQUEST_VIBRATE_PERMISSION;
+				break;
 
 			default:
-				// Check if the given permission is a dangerous permission
-				try {
-					PermissionInfo permissionInfo = getPermissionInfo(activity, permissionName);
-					int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
-					if ((protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permissionName) != PackageManager.PERMISSION_GRANTED) {
-						activity.requestPermissions(new String[] { permissionName }, REQUEST_SINGLE_PERMISSION_REQ_CODE);
-						return false;
-					}
-				} catch (PackageManager.NameNotFoundException e) {
-					// Unknown permission - return false as it can't be granted.
-					Log.w(TAG, "Unable to identify permission " + permissionName, e);
-					return false;
-				}
-				return true;
+				updatedPermissionName = permissionName;
+				requestCode = REQUEST_SINGLE_PERMISSION_REQ_CODE;
+				break;
 		}
+
+		List<String> permissions = Collections.singletonList(updatedPermissionName);
+		return requestPermissions(activity, permissions, requestCode);
 	}
 
 	/**