You've already forked godot
							
							
				mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 12:00:25 +00:00 
			
		
		
		
	Bump the minimum supported SDK version to 24
Raise the minimum supported Android version from Android 5 (Lollipop) to Android 7 (Nougat).
This commit is contained in:
		@@ -73,7 +73,7 @@ def get_ndk_version():
 | 
			
		||||
 | 
			
		||||
# This is kept in sync with the value in 'platform/android/java/app/config.gradle'.
 | 
			
		||||
def get_min_target_api():
 | 
			
		||||
    return 21
 | 
			
		||||
    return 24
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_flags():
 | 
			
		||||
 
 | 
			
		||||
@@ -281,8 +281,7 @@ static const int EXPORT_FORMAT_AAB = 1;
 | 
			
		||||
static const char *APK_ASSETS_DIRECTORY = "assets";
 | 
			
		||||
static const char *AAB_ASSETS_DIRECTORY = "assetPacks/installTime/src/main/assets";
 | 
			
		||||
 | 
			
		||||
static const int OPENGL_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
 | 
			
		||||
static const int VULKAN_MIN_SDK_VERSION = 24;
 | 
			
		||||
static const int DEFAULT_MIN_SDK_VERSION = 24; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
 | 
			
		||||
static const int DEFAULT_TARGET_SDK_VERSION = 35; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
 | 
			
		||||
 | 
			
		||||
#ifndef ANDROID_ENABLED
 | 
			
		||||
@@ -1963,7 +1962,6 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport
 | 
			
		||||
			}
 | 
			
		||||
		} else if (p_name == "gradle_build/min_sdk") {
 | 
			
		||||
			String min_sdk_str = p_preset->get("gradle_build/min_sdk");
 | 
			
		||||
			int min_sdk_int = VULKAN_MIN_SDK_VERSION;
 | 
			
		||||
			bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
 | 
			
		||||
			if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
 | 
			
		||||
				if (!gradle_build_enabled) {
 | 
			
		||||
@@ -1972,9 +1970,9 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport
 | 
			
		||||
				if (!min_sdk_str.is_valid_int()) {
 | 
			
		||||
					return vformat(TTR("\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."), min_sdk_str);
 | 
			
		||||
				} else {
 | 
			
		||||
					min_sdk_int = min_sdk_str.to_int();
 | 
			
		||||
					if (min_sdk_int < OPENGL_MIN_SDK_VERSION) {
 | 
			
		||||
						return vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), OPENGL_MIN_SDK_VERSION);
 | 
			
		||||
					int min_sdk_int = min_sdk_str.to_int();
 | 
			
		||||
					if (min_sdk_int < DEFAULT_MIN_SDK_VERSION) {
 | 
			
		||||
						return vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), DEFAULT_MIN_SDK_VERSION);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -1983,7 +1981,7 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport
 | 
			
		||||
			int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
 | 
			
		||||
 | 
			
		||||
			String min_sdk_str = p_preset->get("gradle_build/min_sdk");
 | 
			
		||||
			int min_sdk_int = VULKAN_MIN_SDK_VERSION;
 | 
			
		||||
			int min_sdk_int = DEFAULT_MIN_SDK_VERSION;
 | 
			
		||||
			if (min_sdk_str.is_valid_int()) {
 | 
			
		||||
				min_sdk_int = min_sdk_str.to_int();
 | 
			
		||||
			}
 | 
			
		||||
@@ -2032,7 +2030,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
 | 
			
		||||
	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "gradle_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK, false, true));
 | 
			
		||||
	// Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465).
 | 
			
		||||
	// This implies doing validation that the string is a proper int.
 | 
			
		||||
	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), "", false, true));
 | 
			
		||||
	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_MIN_SDK_VERSION)), "", false, true));
 | 
			
		||||
	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), "", false, true));
 | 
			
		||||
 | 
			
		||||
#ifndef DISABLE_DEPRECATED
 | 
			
		||||
@@ -2903,14 +2901,6 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	String min_sdk_str = p_preset->get("gradle_build/min_sdk");
 | 
			
		||||
	int min_sdk_int = VULKAN_MIN_SDK_VERSION;
 | 
			
		||||
	if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
 | 
			
		||||
		if (min_sdk_str.is_valid_int()) {
 | 
			
		||||
			min_sdk_int = min_sdk_str.to_int();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	String target_sdk_str = p_preset->get("gradle_build/target_sdk");
 | 
			
		||||
	int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
 | 
			
		||||
	if (!target_sdk_str.is_empty()) { // Empty means no override, nothing to do.
 | 
			
		||||
@@ -2931,12 +2921,6 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
 | 
			
		||||
		err += "\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (_uses_vulkan(p_preset) && min_sdk_int < VULKAN_MIN_SDK_VERSION) {
 | 
			
		||||
		// Warning only, so don't override `valid`.
 | 
			
		||||
		err += vformat(TTR("\"Min SDK\" should be greater or equal to %d for the \"%s\" renderer."), VULKAN_MIN_SDK_VERSION, current_renderer);
 | 
			
		||||
		err += "\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	String package_name = p_preset->get("package/unique_name");
 | 
			
		||||
	if (package_name.contains("$genname") && !is_project_name_valid(p_preset)) {
 | 
			
		||||
		// Warning only, so don't override `valid`.
 | 
			
		||||
@@ -3507,7 +3491,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
 | 
			
		||||
		String version_name = p_preset->get_version("version/name");
 | 
			
		||||
		String min_sdk_version = p_preset->get("gradle_build/min_sdk");
 | 
			
		||||
		if (!min_sdk_version.is_valid_int()) {
 | 
			
		||||
			min_sdk_version = itos(VULKAN_MIN_SDK_VERSION);
 | 
			
		||||
			min_sdk_version = itos(DEFAULT_MIN_SDK_VERSION);
 | 
			
		||||
		}
 | 
			
		||||
		String target_sdk_version = p_preset->get("gradle_build/target_sdk");
 | 
			
		||||
		if (!target_sdk_version.is_valid_int()) {
 | 
			
		||||
@@ -3947,6 +3931,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
 | 
			
		||||
 | 
			
		||||
	// Let's zip-align (must be done before signing)
 | 
			
		||||
 | 
			
		||||
	static const int PAGE_SIZE_KB = 16 * 1024;
 | 
			
		||||
	static const int ZIP_ALIGNMENT = 4;
 | 
			
		||||
 | 
			
		||||
	// If we're not signing the apk, then the next step should be the last.
 | 
			
		||||
@@ -3998,7 +3983,12 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
 | 
			
		||||
		if (!info.compression_method) {
 | 
			
		||||
			// Uncompressed file => Align
 | 
			
		||||
			long new_offset = file_offset + bias;
 | 
			
		||||
			padding = (ZIP_ALIGNMENT - (new_offset % ZIP_ALIGNMENT)) % ZIP_ALIGNMENT;
 | 
			
		||||
			const char *ext = strrchr(fname, '.');
 | 
			
		||||
			if (ext && strcmp(ext, ".so") == 0) {
 | 
			
		||||
				padding = (PAGE_SIZE_KB - (new_offset % PAGE_SIZE_KB)) % PAGE_SIZE_KB;
 | 
			
		||||
			} else {
 | 
			
		||||
				padding = (ZIP_ALIGNMENT - (new_offset % ZIP_ALIGNMENT)) % ZIP_ALIGNMENT;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memset(extra + info.size_file_extra, 0, padding);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
ext.versions = [
 | 
			
		||||
    androidGradlePlugin: '8.6.1',
 | 
			
		||||
    compileSdk         : 35,
 | 
			
		||||
    // Also update 'platform/android/export/export_plugin.cpp#OPENGL_MIN_SDK_VERSION'
 | 
			
		||||
    minSdk             : 21,
 | 
			
		||||
    // Also update:
 | 
			
		||||
    // - 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION'
 | 
			
		||||
    // - 'platform/android/detect.py#get_min_target_api()'
 | 
			
		||||
    minSdk             : 24,
 | 
			
		||||
    // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
 | 
			
		||||
    targetSdk          : 35,
 | 
			
		||||
    buildTools         : '35.0.0',
 | 
			
		||||
@@ -382,17 +384,12 @@ ext.shouldNotStrip = { ->
 | 
			
		||||
 */
 | 
			
		||||
ext.shouldUseLegacyPackaging = { ->
 | 
			
		||||
    int minSdk = getExportMinSdkVersion()
 | 
			
		||||
    if (minSdk < 23) {
 | 
			
		||||
        // Enforce the default behavior for compatibility with device running api < 23
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    String legacyPackagingFlag = project.hasProperty("compress_native_libraries") ? project.property("compress_native_libraries") : ""
 | 
			
		||||
    if (legacyPackagingFlag != null && !legacyPackagingFlag.isEmpty()) {
 | 
			
		||||
        return Boolean.parseBoolean(legacyPackagingFlag)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Default behavior for minSdk >= 23
 | 
			
		||||
    // Default behavior for minSdk >= 24
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -162,7 +162,6 @@ android {
 | 
			
		||||
            }
 | 
			
		||||
            applicationIdSuffix ".meta"
 | 
			
		||||
            versionNameSuffix "-meta"
 | 
			
		||||
            minSdkVersion 23
 | 
			
		||||
            targetSdkVersion 32
 | 
			
		||||
        }
 | 
			
		||||
        picoos {
 | 
			
		||||
 
 | 
			
		||||
@@ -192,13 +192,11 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
 | 
			
		||||
			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,
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
		excludedPermissions.add(
 | 
			
		||||
			// The REQUEST_INSTALL_PACKAGES permission is requested the first time we attempt to
 | 
			
		||||
			// open an apk file.
 | 
			
		||||
			Manifest.permission.REQUEST_INSTALL_PACKAGES,
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		// XR runtime permissions should only be requested when the "xr/openxr/enabled" project setting
 | 
			
		||||
		// is enabled.
 | 
			
		||||
@@ -384,10 +382,8 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
 | 
			
		||||
 | 
			
		||||
		val launchPolicy = resolveLaunchPolicyIfNeeded(editorWindowInfo.launchPolicy)
 | 
			
		||||
		if (launchPolicy == LaunchPolicy.ADJACENT) {
 | 
			
		||||
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
				Log.v(TAG, "Adding flag for adjacent launch")
 | 
			
		||||
				newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
 | 
			
		||||
			}
 | 
			
		||||
			Log.v(TAG, "Adding flag for adjacent launch")
 | 
			
		||||
			newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
 | 
			
		||||
		}
 | 
			
		||||
		return newInstance
 | 
			
		||||
	}
 | 
			
		||||
@@ -511,12 +507,7 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
 | 
			
		||||
	private fun resolveGameEmbedModeIfNeeded(embedMode: GameEmbedMode): GameEmbedMode {
 | 
			
		||||
		return when (embedMode) {
 | 
			
		||||
			GameEmbedMode.AUTO -> {
 | 
			
		||||
				val inMultiWindowMode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
					isInMultiWindowMode
 | 
			
		||||
				} else {
 | 
			
		||||
					false
 | 
			
		||||
				}
 | 
			
		||||
				if (inMultiWindowMode || isLargeScreen || isNativeXRDevice(applicationContext)) {
 | 
			
		||||
				if (isInMultiWindowMode || isLargeScreen || isNativeXRDevice(applicationContext)) {
 | 
			
		||||
					GameEmbedMode.DISABLED
 | 
			
		||||
				} else {
 | 
			
		||||
					GameEmbedMode.ENABLED
 | 
			
		||||
@@ -534,12 +525,7 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
 | 
			
		||||
	private fun resolveLaunchPolicyIfNeeded(policy: LaunchPolicy): LaunchPolicy {
 | 
			
		||||
		return when (policy) {
 | 
			
		||||
			LaunchPolicy.AUTO -> {
 | 
			
		||||
				val inMultiWindowMode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
					isInMultiWindowMode
 | 
			
		||||
				} else {
 | 
			
		||||
					false
 | 
			
		||||
				}
 | 
			
		||||
				val defaultLaunchPolicy = if (inMultiWindowMode || isLargeScreen || isNativeXRDevice(applicationContext)) {
 | 
			
		||||
				val defaultLaunchPolicy = if (isInMultiWindowMode || isLargeScreen || isNativeXRDevice(applicationContext)) {
 | 
			
		||||
					LaunchPolicy.ADJACENT
 | 
			
		||||
				} else {
 | 
			
		||||
					LaunchPolicy.SAME
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ open class GodotGame : BaseGodotGame() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	override fun enterPiPMode() {
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && hasPiPSystemFeature()) {
 | 
			
		||||
		if (hasPiPSystemFeature()) {
 | 
			
		||||
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 | 
			
		||||
				val builder = PictureInPictureParams.Builder().setSourceRectHint(gameViewSourceRectHint)
 | 
			
		||||
				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
 | 
			
		||||
@@ -101,8 +101,7 @@ open class GodotGame : BaseGodotGame() {
 | 
			
		||||
	 * Returns true the if the device supports picture-in-picture (PiP).
 | 
			
		||||
	 */
 | 
			
		||||
	protected fun hasPiPSystemFeature(): Boolean {
 | 
			
		||||
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
 | 
			
		||||
			packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
 | 
			
		||||
		return packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	override fun shouldShowGameMenuBar(): Boolean {
 | 
			
		||||
@@ -123,8 +122,7 @@ open class GodotGame : BaseGodotGame() {
 | 
			
		||||
	override fun onStop() {
 | 
			
		||||
		super.onStop()
 | 
			
		||||
 | 
			
		||||
		val isInPiPMode = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode
 | 
			
		||||
		if (isInPiPMode && !isFinishing) {
 | 
			
		||||
		if (isInPictureInPictureMode && !isFinishing) {
 | 
			
		||||
			// We get in this state when PiP is closed, so we terminate the activity.
 | 
			
		||||
			finish()
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -225,19 +225,12 @@ public class Helpers {
 | 
			
		||||
        return path;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 | 
			
		||||
    static public String getSaveFilePath(Context c) {
 | 
			
		||||
        // This technically existed since Honeycomb, but it is critical
 | 
			
		||||
        // on KitKat and greater versions since it will create the
 | 
			
		||||
        // directory if needed
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
 | 
			
		||||
            return c.getObbDir().toString();
 | 
			
		||||
        } else {
 | 
			
		||||
            File root = Environment.getExternalStorageDirectory();
 | 
			
		||||
            String path = root.toString() + Constants.EXP_PATH + c.getPackageName();
 | 
			
		||||
            return path;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
		return c.getObbDir().toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Helper function to ascertain the existence of a file and return true/false appropriately
 | 
			
		||||
@@ -297,7 +290,7 @@ public class Helpers {
 | 
			
		||||
    /**
 | 
			
		||||
     * Helper function to ascertain whether the application has the correct access to the OBB
 | 
			
		||||
     * directory to allow an OBB file to be written.
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param c the app/activity/service context
 | 
			
		||||
     * @return true if the application can write an OBB file, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
@@ -317,7 +310,7 @@ public class Helpers {
 | 
			
		||||
     * Converts download states that are returned by the
 | 
			
		||||
     * {@link IDownloaderClient#onDownloadStateChanged} callback into usable strings. This is useful
 | 
			
		||||
     * if using the state strings built into the library to display user messages.
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @param state One of the STATE_* constants from {@link IDownloaderClient}.
 | 
			
		||||
     * @return string resource ID for the corresponding string.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -865,16 +865,13 @@ class Godot(private val context: Context) {
 | 
			
		||||
		if (packageManager == null) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			if (!packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL, 1)) {
 | 
			
		||||
				// Optional requirements.. log as warning if missing
 | 
			
		||||
				Log.w(TAG, "The vulkan hardware level does not meet the minimum requirement: 1")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Check for api version 1.0
 | 
			
		||||
			return packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x400003)
 | 
			
		||||
		if (!packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL, 1)) {
 | 
			
		||||
			// Optional requirements.. log as warning if missing
 | 
			
		||||
			Log.w(TAG, "The vulkan hardware level does not meet the minimum requirement: 1")
 | 
			
		||||
		}
 | 
			
		||||
		return false
 | 
			
		||||
 | 
			
		||||
		// Check for api version 1.0
 | 
			
		||||
		return packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x400003)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private fun setKeepScreenOn(enabled: Boolean) {
 | 
			
		||||
 
 | 
			
		||||
@@ -221,14 +221,8 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
 | 
			
		||||
			Intent notifierIntent = new Intent(activity, activity.getClass());
 | 
			
		||||
			notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
 | 
			
		||||
 | 
			
		||||
			PendingIntent pendingIntent;
 | 
			
		||||
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 | 
			
		||||
				pendingIntent = PendingIntent.getActivity(activity, 0,
 | 
			
		||||
						notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
 | 
			
		||||
			} else {
 | 
			
		||||
				pendingIntent = PendingIntent.getActivity(activity, 0,
 | 
			
		||||
						notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 | 
			
		||||
			}
 | 
			
		||||
			PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0,
 | 
			
		||||
					notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
 | 
			
		||||
 | 
			
		||||
			int startResult;
 | 
			
		||||
			try {
 | 
			
		||||
 
 | 
			
		||||
@@ -90,9 +90,7 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
 | 
			
		||||
		this.godot = godot;
 | 
			
		||||
		this.inputHandler = inputHandler;
 | 
			
		||||
		this.godotRenderer = new GodotRenderer();
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
 | 
			
		||||
		}
 | 
			
		||||
		setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
 | 
			
		||||
		init(xrMode, false, useDebugOpengl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -199,27 +197,25 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
 | 
			
		||||
	@Keep
 | 
			
		||||
	@Override
 | 
			
		||||
	public void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY) {
 | 
			
		||||
		if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
 | 
			
		||||
			try {
 | 
			
		||||
				Bitmap bitmap = null;
 | 
			
		||||
				if (!TextUtils.isEmpty(imagePath)) {
 | 
			
		||||
					if (godot.getDirectoryAccessHandler().filesystemFileExists(imagePath)) {
 | 
			
		||||
						// Try to load the bitmap from the file system
 | 
			
		||||
						bitmap = BitmapFactory.decodeFile(imagePath);
 | 
			
		||||
					} else if (godot.getDirectoryAccessHandler().assetsFileExists(imagePath)) {
 | 
			
		||||
						// Try to load the bitmap from the assets directory
 | 
			
		||||
						AssetManager am = getContext().getAssets();
 | 
			
		||||
						InputStream imageInputStream = am.open(imagePath);
 | 
			
		||||
						bitmap = BitmapFactory.decodeStream(imageInputStream);
 | 
			
		||||
					}
 | 
			
		||||
		try {
 | 
			
		||||
			Bitmap bitmap = null;
 | 
			
		||||
			if (!TextUtils.isEmpty(imagePath)) {
 | 
			
		||||
				if (godot.getDirectoryAccessHandler().filesystemFileExists(imagePath)) {
 | 
			
		||||
					// Try to load the bitmap from the file system
 | 
			
		||||
					bitmap = BitmapFactory.decodeFile(imagePath);
 | 
			
		||||
				} else if (godot.getDirectoryAccessHandler().assetsFileExists(imagePath)) {
 | 
			
		||||
					// Try to load the bitmap from the assets directory
 | 
			
		||||
					AssetManager am = getContext().getAssets();
 | 
			
		||||
					InputStream imageInputStream = am.open(imagePath);
 | 
			
		||||
					bitmap = BitmapFactory.decodeStream(imageInputStream);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY);
 | 
			
		||||
				customPointerIcons.put(pointerType, customPointerIcon);
 | 
			
		||||
			} catch (Exception e) {
 | 
			
		||||
				// Reset the custom pointer icon
 | 
			
		||||
				customPointerIcons.delete(pointerType);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY);
 | 
			
		||||
			customPointerIcons.put(pointerType, customPointerIcon);
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			// Reset the custom pointer icon
 | 
			
		||||
			customPointerIcons.delete(pointerType);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -229,21 +225,16 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
 | 
			
		||||
	@Keep
 | 
			
		||||
	@Override
 | 
			
		||||
	public void setPointerIcon(int pointerType) {
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			PointerIcon pointerIcon = customPointerIcons.get(pointerType);
 | 
			
		||||
			if (pointerIcon == null) {
 | 
			
		||||
				pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
 | 
			
		||||
			}
 | 
			
		||||
			setPointerIcon(pointerIcon);
 | 
			
		||||
		PointerIcon pointerIcon = customPointerIcons.get(pointerType);
 | 
			
		||||
		if (pointerIcon == null) {
 | 
			
		||||
			pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
 | 
			
		||||
		}
 | 
			
		||||
		setPointerIcon(pointerIcon);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			return getPointerIcon();
 | 
			
		||||
		}
 | 
			
		||||
		return super.onResolvePointerIcon(me, pointerIndex);
 | 
			
		||||
		return getPointerIcon();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) {
 | 
			
		||||
 
 | 
			
		||||
@@ -64,9 +64,7 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
 | 
			
		||||
		this.godot = godot;
 | 
			
		||||
		mInputHandler = inputHandler;
 | 
			
		||||
		mRenderer = new VkRenderer();
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
 | 
			
		||||
		}
 | 
			
		||||
		setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
 | 
			
		||||
		setFocusableInTouchMode(true);
 | 
			
		||||
		setClickable(false);
 | 
			
		||||
	}
 | 
			
		||||
@@ -179,27 +177,25 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
 | 
			
		||||
	@Keep
 | 
			
		||||
	@Override
 | 
			
		||||
	public void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY) {
 | 
			
		||||
		if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
 | 
			
		||||
			try {
 | 
			
		||||
				Bitmap bitmap = null;
 | 
			
		||||
				if (!TextUtils.isEmpty(imagePath)) {
 | 
			
		||||
					if (godot.getDirectoryAccessHandler().filesystemFileExists(imagePath)) {
 | 
			
		||||
						// Try to load the bitmap from the file system
 | 
			
		||||
						bitmap = BitmapFactory.decodeFile(imagePath);
 | 
			
		||||
					} else if (godot.getDirectoryAccessHandler().assetsFileExists(imagePath)) {
 | 
			
		||||
						// Try to load the bitmap from the assets directory
 | 
			
		||||
						AssetManager am = getContext().getAssets();
 | 
			
		||||
						InputStream imageInputStream = am.open(imagePath);
 | 
			
		||||
						bitmap = BitmapFactory.decodeStream(imageInputStream);
 | 
			
		||||
					}
 | 
			
		||||
		try {
 | 
			
		||||
			Bitmap bitmap = null;
 | 
			
		||||
			if (!TextUtils.isEmpty(imagePath)) {
 | 
			
		||||
				if (godot.getDirectoryAccessHandler().filesystemFileExists(imagePath)) {
 | 
			
		||||
					// Try to load the bitmap from the file system
 | 
			
		||||
					bitmap = BitmapFactory.decodeFile(imagePath);
 | 
			
		||||
				} else if (godot.getDirectoryAccessHandler().assetsFileExists(imagePath)) {
 | 
			
		||||
					// Try to load the bitmap from the assets directory
 | 
			
		||||
					AssetManager am = getContext().getAssets();
 | 
			
		||||
					InputStream imageInputStream = am.open(imagePath);
 | 
			
		||||
					bitmap = BitmapFactory.decodeStream(imageInputStream);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY);
 | 
			
		||||
				customPointerIcons.put(pointerType, customPointerIcon);
 | 
			
		||||
			} catch (Exception e) {
 | 
			
		||||
				// Reset the custom pointer icon
 | 
			
		||||
				customPointerIcons.delete(pointerType);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			PointerIcon customPointerIcon = PointerIcon.create(bitmap, hotSpotX, hotSpotY);
 | 
			
		||||
			customPointerIcons.put(pointerType, customPointerIcon);
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			// Reset the custom pointer icon
 | 
			
		||||
			customPointerIcons.delete(pointerType);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -209,20 +205,15 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
 | 
			
		||||
	@Keep
 | 
			
		||||
	@Override
 | 
			
		||||
	public void setPointerIcon(int pointerType) {
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			PointerIcon pointerIcon = customPointerIcons.get(pointerType);
 | 
			
		||||
			if (pointerIcon == null) {
 | 
			
		||||
				pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
 | 
			
		||||
			}
 | 
			
		||||
			setPointerIcon(pointerIcon);
 | 
			
		||||
		PointerIcon pointerIcon = customPointerIcons.get(pointerType);
 | 
			
		||||
		if (pointerIcon == null) {
 | 
			
		||||
			pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
 | 
			
		||||
		}
 | 
			
		||||
		setPointerIcon(pointerIcon);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			return getPointerIcon();
 | 
			
		||||
		}
 | 
			
		||||
		return super.onResolvePointerIcon(me, pointerIndex);
 | 
			
		||||
		return getPointerIcon();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -103,9 +103,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
 | 
			
		||||
		this.gestureDetector = new GestureDetector(context, godotGestureHandler);
 | 
			
		||||
		this.gestureDetector.setIsLongpressEnabled(false);
 | 
			
		||||
		this.scaleGestureDetector = new ScaleGestureDetector(context, godotGestureHandler);
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 | 
			
		||||
			this.scaleGestureDetector.setStylusScaleEnabled(true);
 | 
			
		||||
		}
 | 
			
		||||
		this.scaleGestureDetector.setStylusScaleEnabled(true);
 | 
			
		||||
		Configuration config = context.getResources().getConfiguration();
 | 
			
		||||
		hasHardwareKeyboardConfig = config.keyboard != Configuration.KEYBOARD_NOKEYS &&
 | 
			
		||||
				config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
 | 
			
		||||
@@ -297,7 +295,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && gestureDetector.onGenericMotionEvent(event)) {
 | 
			
		||||
		if (gestureDetector.onGenericMotionEvent(event)) {
 | 
			
		||||
			// The gesture detector has handled the event.
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -150,18 +150,10 @@ internal class FilesystemDirectoryAccess(private val context: Context, private v
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	override fun getDriveCount(): Int {
 | 
			
		||||
		return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
			storageManager.storageVolumes.size
 | 
			
		||||
		} else {
 | 
			
		||||
			0
 | 
			
		||||
		}
 | 
			
		||||
		return storageManager.storageVolumes.size
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	override fun getDrive(drive: Int): String {
 | 
			
		||||
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (drive < 0 || drive >= storageManager.storageVolumes.size) {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -87,11 +87,6 @@ public final class PermissionsUtil {
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
 | 
			
		||||
			// Not necessary, asked on install already
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		boolean dispatchedPermissionsRequest = false;
 | 
			
		||||
		Set<String> requestedPermissions = new HashSet<>();
 | 
			
		||||
		for (String permission : permissions) {
 | 
			
		||||
@@ -201,10 +196,6 @@ public final class PermissionsUtil {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		List<String> manifestPermissions;
 | 
			
		||||
		try {
 | 
			
		||||
			manifestPermissions = getManifestPermissions(activity);
 | 
			
		||||
 
 | 
			
		||||
@@ -40,11 +40,10 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
 | 
			
		||||
 | 
			
		||||
	_cls = (jclass)env->NewGlobalRef(env->GetObjectClass(godot_view));
 | 
			
		||||
 | 
			
		||||
	_configure_pointer_icon = env->GetMethodID(_cls, "configurePointerIcon", "(ILjava/lang/String;FF)V");
 | 
			
		||||
	_set_pointer_icon = env->GetMethodID(_cls, "setPointerIcon", "(I)V");
 | 
			
		||||
 | 
			
		||||
	int android_device_api_level = android_get_device_api_level();
 | 
			
		||||
	if (android_device_api_level >= __ANDROID_API_N__) {
 | 
			
		||||
		_configure_pointer_icon = env->GetMethodID(_cls, "configurePointerIcon", "(ILjava/lang/String;FF)V");
 | 
			
		||||
		_set_pointer_icon = env->GetMethodID(_cls, "setPointerIcon", "(I)V");
 | 
			
		||||
	}
 | 
			
		||||
	if (android_device_api_level >= __ANDROID_API_O__) {
 | 
			
		||||
		_request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V");
 | 
			
		||||
		_release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user