diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt index 1057994d33..e6a3ea342f 100644 --- a/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt @@ -30,7 +30,6 @@ package org.godotengine.godot -import android.annotation.SuppressLint import android.app.Activity import android.app.AlertDialog import android.content.* @@ -43,7 +42,6 @@ import android.hardware.Sensor import android.hardware.SensorManager import android.os.* import android.util.Log -import android.util.Rational import android.util.TypedValue import android.view.* import android.widget.FrameLayout @@ -57,27 +55,23 @@ import androidx.core.view.WindowInsetsAnimationCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import com.google.android.vending.expansion.downloader.* -import org.godotengine.godot.error.Error -import org.godotengine.godot.feature.PictureInPictureProvider import org.godotengine.godot.input.GodotEditText import org.godotengine.godot.input.GodotInputHandler import org.godotengine.godot.io.FilePicker import org.godotengine.godot.io.directory.DirectoryAccessHandler import org.godotengine.godot.io.file.FileAccessHandler +import org.godotengine.godot.nativeapi.GodotNativeBridge import org.godotengine.godot.plugin.AndroidRuntimePlugin import org.godotengine.godot.plugin.GodotPlugin import org.godotengine.godot.plugin.GodotPluginRegistry import org.godotengine.godot.tts.GodotTTS -import org.godotengine.godot.utils.DialogUtils import org.godotengine.godot.utils.GodotNetUtils import org.godotengine.godot.utils.PermissionsUtil import org.godotengine.godot.utils.PermissionsUtil.requestPermission import org.godotengine.godot.utils.beginBenchmarkMeasure import org.godotengine.godot.utils.benchmarkFile -import org.godotengine.godot.utils.dumpBenchmark import org.godotengine.godot.utils.endBenchmarkMeasure import org.godotengine.godot.utils.useBenchmark -import org.godotengine.godot.variant.Callable as GodotCallable import org.godotengine.godot.xr.XRMode import java.io.File import java.io.FileInputStream @@ -89,7 +83,6 @@ import java.util.concurrent.FutureTask import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference - /** * Core component used to interface with the native layer of the engine. * @@ -131,10 +124,11 @@ class Godot private constructor(val context: Context) { TERMINATING } + private val godotNativeBridge = GodotNativeBridge(this) + private val mSensorManager: SensorManager? by lazy { context.getSystemService(Context.SENSOR_SERVICE) as? SensorManager } private val mClipboard: ClipboardManager? by lazy { context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager } - private val vibratorService: Vibrator? by lazy { context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator } - private val pluginRegistry: GodotPluginRegistry by lazy { GodotPluginRegistry.getPluginRegistry() } + internal val pluginRegistry: GodotPluginRegistry by lazy { GodotPluginRegistry.getPluginRegistry() } private val accelerometerEnabled = AtomicBoolean(false) private val mAccelerometer: Sensor? by lazy { mSensorManager?.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) } @@ -154,7 +148,7 @@ class Godot private constructor(val context: Context) { val directoryAccessHandler = DirectoryAccessHandler(context) val fileAccessHandler = FileAccessHandler(context) val netUtils = GodotNetUtils(context) - private val godotInputHandler = GodotInputHandler(context, this) + val godotInputHandler = GodotInputHandler(context, this) private val hasClipboardCallable = Callable { mClipboard?.hasPrimaryClip() == true @@ -185,7 +179,7 @@ class Godot private constructor(val context: Context) { * Tracks whether [onInitRenderView] was completed successfully. */ private var renderViewInitialized = false - private var primaryHost: GodotHost? = null + internal var primaryHost: GodotHost? = null /** * Tracks whether we're in the RESUMED lifecycle state. @@ -203,11 +197,11 @@ class Godot private constructor(val context: Context) { val io = GodotIO(this) private var commandLine : MutableList = ArrayList() - private var xrMode = XRMode.REGULAR + internal var xrMode = XRMode.REGULAR private val useImmersive = AtomicBoolean(false) private val isEdgeToEdge = AtomicBoolean(false) private var useDebugOpengl = false - private var darkMode = false + internal var darkMode = false private var backgroundColor: Int = Color.BLACK private var orientation = Configuration.ORIENTATION_UNDEFINED @@ -351,7 +345,7 @@ class Godot private constructor(val context: Context) { } if (!nativeLayerInitializeCompleted) { nativeLayerInitializeCompleted = GodotLib.initialize( - this, + godotNativeBridge, context.assets, io, netUtils, @@ -474,20 +468,8 @@ class Godot private constructor(val context: Context) { } } - /** - * Invoked from the render thread to toggle the immersive mode. - */ - @Keep - private fun nativeEnableImmersiveMode(enabled: Boolean) { - runOnHostThread { - enableImmersiveMode(enabled) - } - } - - @Keep fun isInImmersiveMode() = useImmersive.get() - @Keep fun isInEdgeToEdgeMode() = isEdgeToEdge.get() fun setSystemBarsAppearance() { @@ -833,7 +815,7 @@ class Godot private constructor(val context: Context) { /** * Invoked on the render thread when the Godot setup is complete. */ - private fun onGodotSetupCompleted() { + internal fun onGodotSetupCompleted() { Log.v(TAG, "OnGodotSetupCompleted") // These properties are defined after Godot setup completion, so we retrieve them here. @@ -844,7 +826,7 @@ class Godot private constructor(val context: Context) { val scrollDeadzoneDisabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/disable_scroll_deadzone")) runOnHostThread { - renderView?.inputHandler?.apply { + godotInputHandler.apply { enableLongPress(longPressEnabled) enablePanningAndScalingGestures(panScaleEnabled) setOverrideVolumeButtons(overrideVolumeButtons) @@ -867,7 +849,7 @@ class Godot private constructor(val context: Context) { /** * Invoked on the render thread when the Godot main loop has started. */ - private fun onGodotMainLoopStarted() { + internal fun onGodotMainLoopStarted() { Log.v(TAG, "OnGodotMainLoopStarted") _runStatus.set(RunStatus.STARTED) @@ -889,8 +871,7 @@ class Godot private constructor(val context: Context) { /** * Invoked on the render thread when the engine is about to terminate. */ - @Keep - private fun onGodotTerminating() { + internal fun onGodotTerminating() { Log.v(TAG, "OnGodotTerminating") _runStatus.set(RunStatus.TERMINATING) @@ -900,9 +881,6 @@ class Godot private constructor(val context: Context) { runOnTerminate.get()?.run() } - private fun restart() { - primaryHost?.onGodotRestartRequested(this) - } fun alert( @StringRes messageResId: Int, @@ -914,7 +892,6 @@ class Godot private constructor(val context: Context) { } @JvmOverloads - @Keep fun alert(message: String, title: String, okCallback: Runnable? = null) { val activity = getActivity() ?: return runOnHostThread { @@ -947,21 +924,16 @@ class Godot private constructor(val context: Context) { primaryHost?.runOnHostThread(action) } - /** - * Returns true if the call is being made on the Ui thread. - */ - private fun isOnUiThread() = Looper.myLooper() == Looper.getMainLooper() - /** * Returns the native rendering driver. */ private fun getNativeRenderer(): String { val rendererInfo = GodotLib.getRendererInfo(meetsVulkanRequirements(context.packageManager)) - var renderingDriverChosen = rendererInfo[0] - var renderingDriverOriginal = rendererInfo[1] - var renderingMethod = rendererInfo[2] - var renderingDriverSource = rendererInfo[3] - var renderingMethodSource = rendererInfo[4] + val renderingDriverChosen = rendererInfo[0] + val renderingDriverOriginal = rendererInfo[1] + val renderingMethod = rendererInfo[2] + val renderingDriverSource = rendererInfo[3] + val renderingMethodSource = rendererInfo[4] Log.d(TAG, """renderingDevice: ${renderingDriverChosen} (${renderingDriverSource}) renderer: ${renderingMethod} (${renderingMethodSource})""") @@ -973,13 +945,6 @@ class Godot private constructor(val context: Context) { return renderingDriverChosen; } - /** - * Returns true if can fallback to OpenGL. - */ - private fun canFallbackToOpenGL(): Boolean { - return java.lang.Boolean.parseBoolean(GodotLib.getGlobal("rendering/rendering_device/fallback_to_opengl3")) - } - /** * Returns true if the device meets the base requirements for Vulkan support, false otherwise. */ @@ -996,7 +961,7 @@ class Godot private constructor(val context: Context) { return packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000) } - private fun setKeepScreenOn(enabled: Boolean) { + internal fun setKeepScreenOn(enabled: Boolean) { runOnHostThread { if (enabled) { getActivity()?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) @@ -1006,22 +971,6 @@ class Godot private constructor(val context: Context) { } } - /** - * Returns true if dark mode is supported, false otherwise. - */ - @Keep - private fun isDarkModeSupported(): Boolean { - return context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_UNDEFINED - } - - /** - * Returns true if dark mode is supported and enabled, false otherwise. - */ - @Keep - private fun isDarkMode(): Boolean { - return darkMode - } - @Keep fun hasClipboard(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P || Looper.getMainLooper().thread == Thread.currentThread()) { @@ -1051,49 +1000,6 @@ class Godot private constructor(val context: Context) { } } - @Keep - private fun showFilePicker(currentDirectory: String, filename: String, fileMode: Int, filters: Array) { - FilePicker.showFilePicker(context, getActivity(), currentDirectory, filename, fileMode, filters) - } - - /** - * This method shows a dialog with multiple buttons. - * - * @param title The title of the dialog. - * @param message The message displayed in the dialog. - * @param buttons An array of button labels to display. - */ - @Keep - private fun showDialog(title: String, message: String, buttons: Array) { - getActivity()?.let { DialogUtils.showDialog(it, title, message, buttons) } - } - - /** - * This method shows a dialog with a text input field, allowing the user to input text. - * - * @param title The title of the input dialog. - * @param message The message displayed in the input dialog. - * @param existingText The existing text that will be pre-filled in the input field. - */ - @Keep - private fun showInputDialog(title: String, message: String, existingText: String) { - getActivity()?.let { DialogUtils.showInputDialog(it, title, message, existingText) } - } - - @Keep - private fun getAccentColor(): Int { - val value = TypedValue() - context.theme.resolveAttribute(android.R.attr.colorAccent, value, true) - return value.data - } - - @Keep - private fun getBaseColor(): Int { - val value = TypedValue() - context.theme.resolveAttribute(android.R.attr.colorBackground, value, true) - return value.data - } - /** * Destroys the Godot Engine and kill the process it's running in. */ @@ -1117,8 +1023,7 @@ class Godot private constructor(val context: Context) { } } - @Keep - private fun forceQuit(instanceId: Int): Boolean { + internal fun forceQuit(instanceId: Int): Boolean { primaryHost?.let { if (instanceId == 0) { it.onGodotForceQuit(this) @@ -1136,50 +1041,6 @@ class Godot private constructor(val context: Context) { runOnRenderThread { GodotLib.back() } } - /** - * Used by the native code (java_godot_wrapper.h) to vibrate the device. - * @param durationMs - */ - @SuppressLint("MissingPermission") - @Keep - private fun vibrate(durationMs: Int, amplitude: Int) { - if (durationMs > 0 && requestPermission("VIBRATE")) { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (amplitude <= -1) { - vibratorService?.vibrate( - VibrationEffect.createOneShot( - durationMs.toLong(), - VibrationEffect.DEFAULT_AMPLITUDE - ) - ) - } else { - vibratorService?.vibrate( - VibrationEffect.createOneShot( - durationMs.toLong(), - amplitude - ) - ) - } - } else { - // deprecated in API 26 - vibratorService?.vibrate(durationMs.toLong()) - } - } catch (e: SecurityException) { - Log.w(TAG, "SecurityException: VIBRATE permission not found. Make sure it is declared in the manifest or enabled in the export preset.") - } - } - } - - /** - * Used by the native code (java_godot_wrapper.h) to access the input fallback mapping. - * @return The input fallback mapping for the current XR mode. - */ - @Keep - private fun getInputFallbackMapping(): String? { - return xrMode.inputFallbackMapping - } - fun requestPermission(name: String?): Boolean { val activity = getActivity() ?: return false return requestPermission(name, activity) @@ -1213,44 +1074,6 @@ class Godot private constructor(val context: Context) { return GodotLib.hasFeature(feature) } - /** - * Internal method used to query whether the host or the registered plugins supports a given feature. - * - * This is invoked by the native code, and should not be confused with [hasFeature] which is the Android version of - * https://docs.godotengine.org/en/stable/classes/class_os.html#class-os-method-has-feature - */ - @Keep - private fun checkInternalFeatureSupport(feature: String): Boolean { - if (primaryHost?.supportsFeature(feature) == true) { - return true - } - - for (plugin in pluginRegistry.allPlugins) { - if (plugin.supportsFeature(feature)) { - return true - } - } - return false - } - - /** - * Get the list of gdextension modules to register. - */ - @Keep - private fun getGDExtensionConfigFiles(): Array { - val configFiles = mutableSetOf() - for (plugin in pluginRegistry.allPlugins) { - configFiles.addAll(plugin.pluginGDExtensionLibrariesPaths) - } - - return configFiles.toTypedArray() - } - - @Keep - private fun getCACertificates(): String { - return GodotNetUtils.getCACertificates() - } - private fun obbIsCorrupted(f: String, mainPackMd5: String): Boolean { return try { val fis: InputStream = FileInputStream(f) @@ -1284,163 +1107,4 @@ class Godot private constructor(val context: Context) { true } } - - @Keep - private fun initInputDevices() { - godotInputHandler.initInputDevices() - } - - @Keep - private fun createNewGodotInstance(args: Array): Int { - return primaryHost?.onNewGodotInstanceRequested(args) ?: -1 - } - - @Keep - private fun nativeBeginBenchmarkMeasure(scope: String, label: String) { - beginBenchmarkMeasure(scope, label) - } - - @Keep - private fun nativeEndBenchmarkMeasure(scope: String, label: String) { - endBenchmarkMeasure(scope, label) - } - - @Keep - private fun nativeDumpBenchmark(benchmarkFile: String) { - dumpBenchmark(fileAccessHandler, benchmarkFile) - } - - @Keep - private fun nativeSignApk(inputPath: String, - outputPath: String, - keystorePath: String, - keystoreUser: String, - keystorePassword: String): Int { - val signResult = primaryHost?.signApk(inputPath, outputPath, keystorePath, keystoreUser, keystorePassword) ?: Error.ERR_UNAVAILABLE - return signResult.toNativeValue() - } - - @Keep - private fun nativeVerifyApk(apkPath: String): Int { - val verifyResult = primaryHost?.verifyApk(apkPath) ?: Error.ERR_UNAVAILABLE - return verifyResult.toNativeValue() - } - - @Keep - private fun nativeOnEditorWorkspaceSelected(workspace: String) { - primaryHost?.onEditorWorkspaceSelected(workspace) - } - - @Keep - private fun nativeOnDistractionFreeModeChanged(enabled: Boolean) { - primaryHost?.onDistractionFreeModeChanged(enabled) - } - - @Keep - private fun nativeBuildEnvConnect(callback: GodotCallable): Boolean { - try { - val buildProvider = primaryHost?.getBuildProvider() - return buildProvider?.buildEnvConnect(callback) ?: false - } catch (e: Exception) { - Log.e(TAG, "Unable to connect to build environment", e) - return false - } - } - - @Keep - private fun nativeBuildEnvDisconnect() { - try { - val buildProvider = primaryHost?.getBuildProvider() - buildProvider?.buildEnvDisconnect() - } catch (e: Exception) { - Log.e(TAG, "Unable to disconnect from build environment", e) - } - } - - @Keep - private fun nativeBuildEnvExecute(buildTool: String, arguments: Array, projectPath: String, buildDir: String, outputCallback: GodotCallable, resultCallback: GodotCallable): Int { - try { - val buildProvider = primaryHost?.getBuildProvider() - return buildProvider?.buildEnvExecute( - buildTool, - arguments, - projectPath, - buildDir, - outputCallback, - resultCallback - ) ?: -1 - } catch (e: Exception) { - Log.e(TAG, "Unable to execute Gradle command in build environment", e); - return -1 - } - } - - @Keep - private fun nativeBuildEnvCancel(jobId: Int) { - try { - val buildProvider = primaryHost?.getBuildProvider() - buildProvider?.buildEnvCancel(jobId) - } catch (e: Exception) { - Log.e(TAG, "Unable to cancel command in build environment", e) - } - } - - @Keep - private fun nativeBuildEnvCleanProject(projectPath: String, buildDir: String, callback: GodotCallable) { - try { - val buildProvider = primaryHost?.getBuildProvider() - buildProvider?.buildEnvCleanProject(projectPath, buildDir, callback) - } catch(e: Exception) { - Log.e(TAG, "Unable to clean project in build environment", e) - } - } - - @Keep - private fun nativeIsPiPModeSupported(): Boolean { - val hostActivity = getActivity() - if (hostActivity is PictureInPictureProvider) { - return hostActivity.isPiPModeSupported() - } - return false - } - - @Keep - private fun nativeIsInPiPMode(): Boolean { - val hostActivity = getActivity() - if (hostActivity is GodotActivity) { - return hostActivity.isInPictureInPictureMode - } - return false - } - - @Keep - private fun nativeEnterPiPMode() { - val hostActivity = getActivity() - if (hostActivity is PictureInPictureProvider) { - runOnHostThread { - hostActivity.enterPiPMode() - } - } - } - - @Keep - private fun nativeSetPiPModeAspectRatio(numerator: Int, denominator: Int) { - val hostActivity = getActivity() - if (hostActivity is GodotActivity) { - runOnHostThread { - hostActivity.updatePiPParams(aspectRatio = Rational(numerator, denominator)) - } - } - } - - @Keep - private fun nativeSetAutoEnterPiPModeOnBackground(autoEnterPiPOnBackground: Boolean) { - val hostActivity = getActivity() - if (hostActivity is GodotActivity) { - runOnHostThread { - hostActivity.updatePiPParams(enableAutoEnter = autoEnterPiPOnBackground) - } - } - } - } diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java index c6d780ceeb..1f7299fa14 100644 --- a/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java @@ -33,6 +33,7 @@ package org.godotengine.godot; import org.godotengine.godot.gl.GodotRenderer; import org.godotengine.godot.io.directory.DirectoryAccessHandler; import org.godotengine.godot.io.file.FileAccessHandler; +import org.godotengine.godot.nativeapi.GodotNativeBridge; import org.godotengine.godot.tts.GodotTTS; import org.godotengine.godot.utils.GodotNetUtils; import org.godotengine.godot.variant.Callable; @@ -56,13 +57,13 @@ public class GodotLib { * Invoked on the main thread to initialize Godot native layer. */ public static native boolean initialize( - Godot p_instance, - AssetManager p_asset_manager, + GodotNativeBridge nativeBridge, + AssetManager assetManager, GodotIO godotIO, GodotNetUtils netUtils, DirectoryAccessHandler directoryAccessHandler, FileAccessHandler fileAccessHandler, - boolean use_apk_expansion); + boolean useApkExpansion); /** * Invoked on the main thread to clean up Godot native layer. diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/nativeapi/GodotNativeBridge.kt b/platform/android/java/lib/src/main/java/org/godotengine/godot/nativeapi/GodotNativeBridge.kt new file mode 100644 index 0000000000..ffdaecb1f0 --- /dev/null +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/nativeapi/GodotNativeBridge.kt @@ -0,0 +1,410 @@ +/**************************************************************************/ +/* GodotNativeBridge.kt */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +package org.godotengine.godot.nativeapi + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.Configuration +import android.os.Build +import android.os.VibrationEffect +import android.os.Vibrator +import android.util.Log +import android.util.Rational +import android.util.TypedValue +import androidx.annotation.Keep +import org.godotengine.godot.Godot +import org.godotengine.godot.GodotActivity +import org.godotengine.godot.GodotLib +import org.godotengine.godot.error.Error +import org.godotengine.godot.feature.PictureInPictureProvider +import org.godotengine.godot.io.FilePicker +import org.godotengine.godot.utils.DialogUtils +import org.godotengine.godot.utils.GodotNetUtils +import org.godotengine.godot.utils.beginBenchmarkMeasure +import org.godotengine.godot.utils.dumpBenchmark +import org.godotengine.godot.utils.endBenchmarkMeasure +import org.godotengine.godot.variant.Callable as GodotCallable + +/** + * Holds and expose Godot apis to the native layer. + * + * All the methods in this class are accessed by the native code (java_godot_wrapper.h) and as such are kept private to + * not be accessible by the rest of the java/kotlin code. + */ +@Keep +internal class GodotNativeBridge(private val godot: Godot) { + + companion object { + private val TAG = GodotNativeBridge::class.java.simpleName + + } + + private val vibratorService: Vibrator? by lazy { godot.context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator } + + /** + * Invoked on the render thread when the Godot setup is complete. + */ + private fun onGodotSetupCompleted() { + godot.onGodotSetupCompleted() + } + + /** + * Invoked on the render thread when the Godot main loop has started. + */ + private fun onGodotMainLoopStarted() { + godot.onGodotMainLoopStarted() + } + + /** + * Invoked on the render thread when the engine is about to terminate. + */ + private fun onGodotTerminating() = godot.onGodotTerminating() + + /** + * Invoked from the render thread to toggle the immersive mode. + */ + private fun nativeEnableImmersiveMode(enabled: Boolean) { + godot.runOnHostThread { + godot.enableImmersiveMode(enabled) + } + } + + private fun isInImmersiveMode() = godot.isInImmersiveMode() + + private fun isInEdgeToEdgeMode() = godot.isInEdgeToEdgeMode() + + private fun setKeepScreenOn(enabled: Boolean) = godot.setKeepScreenOn(enabled) + + private fun restart() { godot.primaryHost?.onGodotRestartRequested(godot) } + + private fun alert(message: String, title: String) { + godot.alert(message, title) + } + + private fun forceQuit(instanceId: Int) = godot.forceQuit(instanceId) + + /** + * Returns true if dark mode is supported, false otherwise. + */ + private fun isDarkModeSupported(): Boolean { + return godot.context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_UNDEFINED + } + + /** + * Returns true if dark mode is supported and enabled, false otherwise. + */ + private fun isDarkMode() = godot.darkMode + + private fun showFilePicker(currentDirectory: String, filename: String, fileMode: Int, filters: Array) { + FilePicker.showFilePicker(godot.context, godot.getActivity(), currentDirectory, filename, fileMode, filters) + } + + /** + * This method shows a dialog with multiple buttons. + * + * @param title The title of the dialog. + * @param message The message displayed in the dialog. + * @param buttons An array of button labels to display. + */ + private fun showDialog(title: String, message: String, buttons: Array) { + godot.getActivity()?.let { DialogUtils.showDialog(it, title, message, buttons) } + } + + /** + * This method shows a dialog with a text input field, allowing the user to input text. + * + * @param title The title of the input dialog. + * @param message The message displayed in the input dialog. + * @param existingText The existing text that will be pre-filled in the input field. + */ + private fun showInputDialog(title: String, message: String, existingText: String) { + godot.getActivity()?.let { DialogUtils.showInputDialog(it, title, message, existingText) } + } + + private fun getAccentColor(): Int { + val value = TypedValue() + godot.context.theme.resolveAttribute(android.R.attr.colorAccent, value, true) + return value.data + } + + private fun getBaseColor(): Int { + val value = TypedValue() + godot.context.theme.resolveAttribute(android.R.attr.colorBackground, value, true) + return value.data + } + + private fun requestPermission(name: String?) = godot.requestPermission(name) + + private fun requestPermissions() = godot.requestPermissions() + + private fun getGrantedPermissions() = godot.getGrantedPermissions() + + /** + * Used by the native code (java_godot_wrapper.h) to vibrate the device. + * @param durationMs + */ + @SuppressLint("MissingPermission") + private fun vibrate(durationMs: Int, amplitude: Int) { + if (durationMs > 0 && godot.requestPermission("VIBRATE")) { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (amplitude <= -1) { + vibratorService?.vibrate( + VibrationEffect.createOneShot( + durationMs.toLong(), + VibrationEffect.DEFAULT_AMPLITUDE + ) + ) + } else { + vibratorService?.vibrate( + VibrationEffect.createOneShot( + durationMs.toLong(), + amplitude + ) + ) + } + } else { + // deprecated in API 26 + vibratorService?.vibrate(durationMs.toLong()) + } + } catch (e: SecurityException) { + Log.w( + TAG, + "SecurityException: VIBRATE permission not found. Make sure it is declared in the manifest or enabled in the export preset." + ) + } + } + } + + /** + * Internal method used to query whether the host or the registered plugins supports a given feature. + * + * This is invoked by the native code, and should not be confused with [hasFeature] which is the Android version of + * https://docs.godotengine.org/en/stable/classes/class_os.html#class-os-method-has-feature + */ + private fun checkInternalFeatureSupport(feature: String): Boolean { + if (godot.primaryHost?.supportsFeature(feature) == true) { + return true + } + + for (plugin in godot.pluginRegistry.allPlugins) { + if (plugin.supportsFeature(feature)) { + return true + } + } + return false + } + + /** + * Get the list of gdextension modules to register. + */ + private fun getGDExtensionConfigFiles(): Array { + val configFiles = mutableSetOf() + for (plugin in godot.pluginRegistry.allPlugins) { + configFiles.addAll(plugin.pluginGDExtensionLibrariesPaths) + } + + return configFiles.toTypedArray() + } + + private fun getCACertificates(): String { + return GodotNetUtils.getCACertificates() + } + + private fun getActivity() = godot.getActivity() + + private fun getRenderView() = godot.renderView + + private fun getClipboard() = godot.getClipboard() + + private fun setClipboard(text: String) = godot.setClipboard(text) + + private fun hasClipboard() = godot.hasClipboard() + + private fun setWindowColor(color: String) = godot.setWindowColor(color) + + /** + * Used by the native code (java_godot_wrapper.h) to access the input fallback mapping. + * @return The input fallback mapping for the current XR mode. + */ + private fun getInputFallbackMapping(): String? { + return godot.xrMode.inputFallbackMapping + } + + private fun initInputDevices() { + godot.godotInputHandler.initInputDevices() + } + + private fun createNewGodotInstance(args: Array): Int { + return godot.primaryHost?.onNewGodotInstanceRequested(args) ?: -1 + } + + private fun nativeBeginBenchmarkMeasure(scope: String, label: String) { + beginBenchmarkMeasure(scope, label) + } + + private fun nativeEndBenchmarkMeasure(scope: String, label: String) { + endBenchmarkMeasure(scope, label) + } + + private fun nativeDumpBenchmark(benchmarkFile: String) { + dumpBenchmark(godot.fileAccessHandler, benchmarkFile) + } + + private fun nativeSignApk( + inputPath: String, + outputPath: String, + keystorePath: String, + keystoreUser: String, + keystorePassword: String + ): Int { + val signResult = godot.primaryHost?.signApk(inputPath, outputPath, keystorePath, keystoreUser, keystorePassword) + ?: org.godotengine.godot.error.Error.ERR_UNAVAILABLE + return signResult.toNativeValue() + } + + private fun nativeVerifyApk(apkPath: String): Int { + val verifyResult = godot.primaryHost?.verifyApk(apkPath) ?: Error.ERR_UNAVAILABLE + return verifyResult.toNativeValue() + } + + private fun nativeOnEditorWorkspaceSelected(workspace: String) { + godot.primaryHost?.onEditorWorkspaceSelected(workspace) + } + + private fun nativeOnDistractionFreeModeChanged(enabled: Boolean) { + godot.primaryHost?.onDistractionFreeModeChanged(enabled) + } + + private fun nativeBuildEnvConnect(callback: GodotCallable): Boolean { + try { + val buildProvider = godot.primaryHost?.getBuildProvider() + return buildProvider?.buildEnvConnect(callback) ?: false + } catch (e: Exception) { + Log.e(TAG, "Unable to connect to build environment", e) + return false + } + } + + private fun nativeBuildEnvDisconnect() { + try { + val buildProvider = godot.primaryHost?.getBuildProvider() + buildProvider?.buildEnvDisconnect() + } catch (e: Exception) { + Log.e(TAG, "Unable to disconnect from build environment", e) + } + } + + private fun nativeBuildEnvExecute( + buildTool: String, + arguments: Array, + projectPath: String, + buildDir: String, + outputCallback: GodotCallable, + resultCallback: GodotCallable + ): Int { + try { + val buildProvider = godot.primaryHost?.getBuildProvider() + return buildProvider?.buildEnvExecute( + buildTool, + arguments, + projectPath, + buildDir, + outputCallback, + resultCallback + ) ?: -1 + } catch (e: Exception) { + Log.e(TAG, "Unable to execute Gradle command in build environment", e); + return -1 + } + } + + private fun nativeBuildEnvCancel(jobId: Int) { + try { + val buildProvider = godot.primaryHost?.getBuildProvider() + buildProvider?.buildEnvCancel(jobId) + } catch (e: Exception) { + Log.e(TAG, "Unable to cancel command in build environment", e) + } + } + + private fun nativeBuildEnvCleanProject(projectPath: String, buildDir: String, callback: GodotCallable) { + try { + val buildProvider = godot.primaryHost?.getBuildProvider() + buildProvider?.buildEnvCleanProject(projectPath, buildDir, callback) + } catch (e: Exception) { + Log.e(TAG, "Unable to clean project in build environment", e) + } + } + + private fun nativeIsPiPModeSupported(): Boolean { + val hostActivity = godot.getActivity() + if (hostActivity is PictureInPictureProvider) { + return hostActivity.isPiPModeSupported() + } + return false + } + + private fun nativeIsInPiPMode(): Boolean { + val hostActivity = godot.getActivity() + if (hostActivity is GodotActivity) { + return hostActivity.isInPictureInPictureMode + } + return false + } + + private fun nativeEnterPiPMode() { + val hostActivity = godot.getActivity() + if (hostActivity is PictureInPictureProvider) { + godot.runOnHostThread { + hostActivity.enterPiPMode() + } + } + } + + private fun nativeSetPiPModeAspectRatio(numerator: Int, denominator: Int) { + val hostActivity = godot.getActivity() + if (hostActivity is GodotActivity) { + godot.runOnHostThread { + hostActivity.updatePiPParams(aspectRatio = Rational(numerator, denominator)) + } + } + } + + private fun nativeSetAutoEnterPiPModeOnBackground(autoEnterPiPOnBackground: Boolean) { + val hostActivity = godot.getActivity() + if (hostActivity is GodotActivity) { + godot.runOnHostThread { + hostActivity.updatePiPParams(enableAutoEnter = autoEnterPiPOnBackground) + } + } + } +} diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index f46c3dabdf..8cb82e485e 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -162,7 +162,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei } } -JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion) { +JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_godot_native_bridge, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion) { godot_init_profiler(); JavaVM *jvm; @@ -172,7 +172,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv setup_android_class_loader(); // create our wrapper classes - godot_java = new GodotJavaWrapper(env, p_godot_instance); + godot_java = new GodotJavaWrapper(env, p_godot_native_bridge); godot_io_java = new GodotIOJavaWrapper(env, p_godot_io); FileAccessAndroid::setup(p_asset_manager); diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 6579c5ca5d..2fea1a2e2b 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -36,7 +36,7 @@ // These functions can be called from within JAVA and are the means by which our JAVA implementation calls back into our C++ code. // See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names) extern "C" { -JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion); +JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_godot_native_bridge, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz); JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline, jobject p_godot_tts); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height); diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index ba880dc8b7..fe13b60347 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -39,70 +39,70 @@ // TODO we could probably create a base class for this... -GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) { - godot_instance = p_env->NewGlobalRef(p_godot_instance); +GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_native_bridge) { + godot_native_bridge = p_env->NewGlobalRef(p_godot_native_bridge); // get info about our Godot class so we can get pointers and stuff... - godot_class = jni_find_class(p_env, "org/godotengine/godot/Godot"); - if (godot_class) { - godot_class = (jclass)p_env->NewGlobalRef(godot_class); + godot_native_bridge_class = jni_find_class(p_env, "org/godotengine/godot/nativeapi/GodotNativeBridge"); + if (godot_native_bridge_class) { + godot_native_bridge_class = (jclass)p_env->NewGlobalRef(godot_native_bridge_class); } else { // this is a pretty serious fail.. bail... pointers will stay 0 return; } // get some Godot method pointers... - _restart = p_env->GetMethodID(godot_class, "restart", "()V"); - _finish = p_env->GetMethodID(godot_class, "forceQuit", "(I)Z"); - _set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V"); - _alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); - _is_dark_mode_supported = p_env->GetMethodID(godot_class, "isDarkModeSupported", "()Z"); - _is_dark_mode = p_env->GetMethodID(godot_class, "isDarkMode", "()Z"); - _get_accent_color = p_env->GetMethodID(godot_class, "getAccentColor", "()I"); - _get_base_color = p_env->GetMethodID(godot_class, "getBaseColor", "()I"); - _get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;"); - _set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V"); - _has_clipboard = p_env->GetMethodID(godot_class, "hasClipboard", "()Z"); - _show_dialog = p_env->GetMethodID(godot_class, "showDialog", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V"); - _show_input_dialog = p_env->GetMethodID(godot_class, "showInputDialog", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); - _show_file_picker = p_env->GetMethodID(godot_class, "showFilePicker", "(Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)V"); - _request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z"); - _request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z"); - _get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;"); - _get_ca_certificates = p_env->GetMethodID(godot_class, "getCACertificates", "()Ljava/lang/String;"); - _init_input_devices = p_env->GetMethodID(godot_class, "initInputDevices", "()V"); - _vibrate = p_env->GetMethodID(godot_class, "vibrate", "(II)V"); - _get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;"); - _on_godot_setup_completed = p_env->GetMethodID(godot_class, "onGodotSetupCompleted", "()V"); - _on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V"); - _on_godot_terminating = p_env->GetMethodID(godot_class, "onGodotTerminating", "()V"); - _create_new_godot_instance = p_env->GetMethodID(godot_class, "createNewGodotInstance", "([Ljava/lang/String;)I"); - _get_render_view = p_env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;"); - _begin_benchmark_measure = p_env->GetMethodID(godot_class, "nativeBeginBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V"); - _end_benchmark_measure = p_env->GetMethodID(godot_class, "nativeEndBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V"); - _dump_benchmark = p_env->GetMethodID(godot_class, "nativeDumpBenchmark", "(Ljava/lang/String;)V"); - _get_gdextension_list_config_file = p_env->GetMethodID(godot_class, "getGDExtensionConfigFiles", "()[Ljava/lang/String;"); - _check_internal_feature_support = p_env->GetMethodID(godot_class, "checkInternalFeatureSupport", "(Ljava/lang/String;)Z"); - _sign_apk = p_env->GetMethodID(godot_class, "nativeSignApk", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I"); - _verify_apk = p_env->GetMethodID(godot_class, "nativeVerifyApk", "(Ljava/lang/String;)I"); - _enable_immersive_mode = p_env->GetMethodID(godot_class, "nativeEnableImmersiveMode", "(Z)V"); - _is_in_immersive_mode = p_env->GetMethodID(godot_class, "isInImmersiveMode", "()Z"); - _set_window_color = p_env->GetMethodID(godot_class, "setWindowColor", "(Ljava/lang/String;)V"); - _on_editor_workspace_selected = p_env->GetMethodID(godot_class, "nativeOnEditorWorkspaceSelected", "(Ljava/lang/String;)V"); - _on_distraction_free_mode_changed = p_env->GetMethodID(godot_class, "nativeOnDistractionFreeModeChanged", "(Z)V"); - _get_activity = p_env->GetMethodID(godot_class, "getActivity", "()Landroid/app/Activity;"); - _build_env_connect = p_env->GetMethodID(godot_class, "nativeBuildEnvConnect", "(Lorg/godotengine/godot/variant/Callable;)Z"); - _build_env_disconnect = p_env->GetMethodID(godot_class, "nativeBuildEnvDisconnect", "()V"); - _build_env_execute = p_env->GetMethodID(godot_class, "nativeBuildEnvExecute", "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/godotengine/godot/variant/Callable;Lorg/godotengine/godot/variant/Callable;)I"); - _build_env_cancel = p_env->GetMethodID(godot_class, "nativeBuildEnvCancel", "(I)V"); - _build_env_clean_project = p_env->GetMethodID(godot_class, "nativeBuildEnvCleanProject", "(Ljava/lang/String;Ljava/lang/String;Lorg/godotengine/godot/variant/Callable;)V"); + _restart = p_env->GetMethodID(godot_native_bridge_class, "restart", "()V"); + _finish = p_env->GetMethodID(godot_native_bridge_class, "forceQuit", "(I)Z"); + _set_keep_screen_on = p_env->GetMethodID(godot_native_bridge_class, "setKeepScreenOn", "(Z)V"); + _alert = p_env->GetMethodID(godot_native_bridge_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); + _is_dark_mode_supported = p_env->GetMethodID(godot_native_bridge_class, "isDarkModeSupported", "()Z"); + _is_dark_mode = p_env->GetMethodID(godot_native_bridge_class, "isDarkMode", "()Z"); + _get_accent_color = p_env->GetMethodID(godot_native_bridge_class, "getAccentColor", "()I"); + _get_base_color = p_env->GetMethodID(godot_native_bridge_class, "getBaseColor", "()I"); + _get_clipboard = p_env->GetMethodID(godot_native_bridge_class, "getClipboard", "()Ljava/lang/String;"); + _set_clipboard = p_env->GetMethodID(godot_native_bridge_class, "setClipboard", "(Ljava/lang/String;)V"); + _has_clipboard = p_env->GetMethodID(godot_native_bridge_class, "hasClipboard", "()Z"); + _show_dialog = p_env->GetMethodID(godot_native_bridge_class, "showDialog", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V"); + _show_input_dialog = p_env->GetMethodID(godot_native_bridge_class, "showInputDialog", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + _show_file_picker = p_env->GetMethodID(godot_native_bridge_class, "showFilePicker", "(Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)V"); + _request_permission = p_env->GetMethodID(godot_native_bridge_class, "requestPermission", "(Ljava/lang/String;)Z"); + _request_permissions = p_env->GetMethodID(godot_native_bridge_class, "requestPermissions", "()Z"); + _get_granted_permissions = p_env->GetMethodID(godot_native_bridge_class, "getGrantedPermissions", "()[Ljava/lang/String;"); + _get_ca_certificates = p_env->GetMethodID(godot_native_bridge_class, "getCACertificates", "()Ljava/lang/String;"); + _init_input_devices = p_env->GetMethodID(godot_native_bridge_class, "initInputDevices", "()V"); + _vibrate = p_env->GetMethodID(godot_native_bridge_class, "vibrate", "(II)V"); + _get_input_fallback_mapping = p_env->GetMethodID(godot_native_bridge_class, "getInputFallbackMapping", "()Ljava/lang/String;"); + _on_godot_setup_completed = p_env->GetMethodID(godot_native_bridge_class, "onGodotSetupCompleted", "()V"); + _on_godot_main_loop_started = p_env->GetMethodID(godot_native_bridge_class, "onGodotMainLoopStarted", "()V"); + _on_godot_terminating = p_env->GetMethodID(godot_native_bridge_class, "onGodotTerminating", "()V"); + _create_new_godot_instance = p_env->GetMethodID(godot_native_bridge_class, "createNewGodotInstance", "([Ljava/lang/String;)I"); + _get_render_view = p_env->GetMethodID(godot_native_bridge_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;"); + _begin_benchmark_measure = p_env->GetMethodID(godot_native_bridge_class, "nativeBeginBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V"); + _end_benchmark_measure = p_env->GetMethodID(godot_native_bridge_class, "nativeEndBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V"); + _dump_benchmark = p_env->GetMethodID(godot_native_bridge_class, "nativeDumpBenchmark", "(Ljava/lang/String;)V"); + _get_gdextension_list_config_file = p_env->GetMethodID(godot_native_bridge_class, "getGDExtensionConfigFiles", "()[Ljava/lang/String;"); + _check_internal_feature_support = p_env->GetMethodID(godot_native_bridge_class, "checkInternalFeatureSupport", "(Ljava/lang/String;)Z"); + _sign_apk = p_env->GetMethodID(godot_native_bridge_class, "nativeSignApk", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I"); + _verify_apk = p_env->GetMethodID(godot_native_bridge_class, "nativeVerifyApk", "(Ljava/lang/String;)I"); + _enable_immersive_mode = p_env->GetMethodID(godot_native_bridge_class, "nativeEnableImmersiveMode", "(Z)V"); + _is_in_immersive_mode = p_env->GetMethodID(godot_native_bridge_class, "isInImmersiveMode", "()Z"); + _set_window_color = p_env->GetMethodID(godot_native_bridge_class, "setWindowColor", "(Ljava/lang/String;)V"); + _on_editor_workspace_selected = p_env->GetMethodID(godot_native_bridge_class, "nativeOnEditorWorkspaceSelected", "(Ljava/lang/String;)V"); + _on_distraction_free_mode_changed = p_env->GetMethodID(godot_native_bridge_class, "nativeOnDistractionFreeModeChanged", "(Z)V"); + _get_activity = p_env->GetMethodID(godot_native_bridge_class, "getActivity", "()Landroid/app/Activity;"); + _build_env_connect = p_env->GetMethodID(godot_native_bridge_class, "nativeBuildEnvConnect", "(Lorg/godotengine/godot/variant/Callable;)Z"); + _build_env_disconnect = p_env->GetMethodID(godot_native_bridge_class, "nativeBuildEnvDisconnect", "()V"); + _build_env_execute = p_env->GetMethodID(godot_native_bridge_class, "nativeBuildEnvExecute", "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/godotengine/godot/variant/Callable;Lorg/godotengine/godot/variant/Callable;)I"); + _build_env_cancel = p_env->GetMethodID(godot_native_bridge_class, "nativeBuildEnvCancel", "(I)V"); + _build_env_clean_project = p_env->GetMethodID(godot_native_bridge_class, "nativeBuildEnvCleanProject", "(Ljava/lang/String;Ljava/lang/String;Lorg/godotengine/godot/variant/Callable;)V"); // PiP mode method ids. - _is_pip_mode_supported = p_env->GetMethodID(godot_class, "nativeIsPiPModeSupported", "()Z"); - _is_in_pip_mode = p_env->GetMethodID(godot_class, "nativeIsInPiPMode", "()Z"); - _enter_pip_mode = p_env->GetMethodID(godot_class, "nativeEnterPiPMode", "()V"); - _set_pip_mode_aspect_ratio = p_env->GetMethodID(godot_class, "nativeSetPiPModeAspectRatio", "(II)V"); - _set_auto_enter_pip_mode_on_background = p_env->GetMethodID(godot_class, "nativeSetAutoEnterPiPModeOnBackground", "(Z)V"); + _is_pip_mode_supported = p_env->GetMethodID(godot_native_bridge_class, "nativeIsPiPModeSupported", "()Z"); + _is_in_pip_mode = p_env->GetMethodID(godot_native_bridge_class, "nativeIsInPiPMode", "()Z"); + _enter_pip_mode = p_env->GetMethodID(godot_native_bridge_class, "nativeEnterPiPMode", "()V"); + _set_pip_mode_aspect_ratio = p_env->GetMethodID(godot_native_bridge_class, "nativeSetPiPModeAspectRatio", "(II)V"); + _set_auto_enter_pip_mode_on_background = p_env->GetMethodID(godot_native_bridge_class, "nativeSetAutoEnterPiPModeOnBackground", "(Z)V"); } GodotJavaWrapper::~GodotJavaWrapper() { @@ -112,15 +112,15 @@ GodotJavaWrapper::~GodotJavaWrapper() { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->DeleteGlobalRef(godot_instance); - env->DeleteGlobalRef(godot_class); + env->DeleteGlobalRef(godot_native_bridge); + env->DeleteGlobalRef(godot_native_bridge_class); } jobject GodotJavaWrapper::get_activity() { if (_get_activity) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, nullptr); - jobject activity = env->CallObjectMethod(godot_instance, _get_activity); + jobject activity = env->CallObjectMethod(godot_native_bridge, _get_activity); return activity; } return nullptr; @@ -133,7 +133,7 @@ GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() { if (_get_render_view) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, nullptr); - jobject godot_render_view = env->CallObjectMethod(godot_instance, _get_render_view); + jobject godot_render_view = env->CallObjectMethod(godot_native_bridge, _get_render_view); if (!env->IsSameObject(godot_render_view, nullptr)) { godot_view = new GodotJavaViewWrapper(godot_render_view); } @@ -146,7 +146,7 @@ void GodotJavaWrapper::on_godot_setup_completed(JNIEnv *p_env) { if (p_env == nullptr) { p_env = get_jni_env(); } - p_env->CallVoidMethod(godot_instance, _on_godot_setup_completed); + p_env->CallVoidMethod(godot_native_bridge, _on_godot_setup_completed); } } @@ -156,7 +156,7 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) { p_env = get_jni_env(); } ERR_FAIL_NULL(p_env); - p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started); + p_env->CallVoidMethod(godot_native_bridge, _on_godot_main_loop_started); } } @@ -166,7 +166,7 @@ void GodotJavaWrapper::on_godot_terminating(JNIEnv *p_env) { p_env = get_jni_env(); } ERR_FAIL_NULL(p_env); - p_env->CallVoidMethod(godot_instance, _on_godot_terminating); + p_env->CallVoidMethod(godot_native_bridge, _on_godot_terminating); } } @@ -176,7 +176,7 @@ void GodotJavaWrapper::restart(JNIEnv *p_env) { p_env = get_jni_env(); } ERR_FAIL_NULL(p_env); - p_env->CallVoidMethod(godot_instance, _restart); + p_env->CallVoidMethod(godot_native_bridge, _restart); } } @@ -186,7 +186,7 @@ bool GodotJavaWrapper::force_quit(JNIEnv *p_env, int p_instance_id) { p_env = get_jni_env(); } ERR_FAIL_NULL_V(p_env, false); - return p_env->CallBooleanMethod(godot_instance, _finish, p_instance_id); + return p_env->CallBooleanMethod(godot_native_bridge, _finish, p_instance_id); } return false; } @@ -195,7 +195,7 @@ void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) { if (_set_keep_screen_on) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled); + env->CallVoidMethod(godot_native_bridge, _set_keep_screen_on, p_enabled); } } @@ -205,7 +205,7 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { ERR_FAIL_NULL(env); jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data()); jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data()); - env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle); + env->CallVoidMethod(godot_native_bridge, _alert, jStrMessage, jStrTitle); env->DeleteLocalRef(jStrMessage); env->DeleteLocalRef(jStrTitle); } @@ -215,7 +215,7 @@ bool GodotJavaWrapper::is_dark_mode_supported() { if (_is_dark_mode_supported) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _is_dark_mode_supported); + return env->CallBooleanMethod(godot_native_bridge, _is_dark_mode_supported); } else { return false; } @@ -225,7 +225,7 @@ bool GodotJavaWrapper::is_dark_mode() { if (_is_dark_mode) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _is_dark_mode); + return env->CallBooleanMethod(godot_native_bridge, _is_dark_mode); } else { return false; } @@ -244,7 +244,7 @@ Color GodotJavaWrapper::get_accent_color() { if (_get_accent_color) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, Color(0, 0, 0, 0)); - int accent_color = env->CallIntMethod(godot_instance, _get_accent_color); + int accent_color = env->CallIntMethod(godot_native_bridge, _get_accent_color); return _argb_to_rgba(accent_color); } else { return Color(0, 0, 0, 0); @@ -255,7 +255,7 @@ Color GodotJavaWrapper::get_base_color() { if (_get_base_color) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, Color(0, 0, 0, 0)); - int base_color = env->CallIntMethod(godot_instance, _get_base_color); + int base_color = env->CallIntMethod(godot_native_bridge, _get_base_color); return _argb_to_rgba(base_color); } else { return Color(0, 0, 0, 0); @@ -271,7 +271,7 @@ String GodotJavaWrapper::get_clipboard() { if (_get_clipboard) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, String()); - jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard); + jstring s = (jstring)env->CallObjectMethod(godot_native_bridge, _get_clipboard); clipboard = jstring_to_string(s, env); env->DeleteLocalRef(s); } @@ -283,7 +283,7 @@ String GodotJavaWrapper::get_input_fallback_mapping() { if (_get_input_fallback_mapping) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, String()); - jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping); + jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_native_bridge, _get_input_fallback_mapping); input_fallback_mapping = jstring_to_string(fallback_mapping, env); env->DeleteLocalRef(fallback_mapping); } @@ -299,7 +299,7 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); jstring jStr = env->NewStringUTF(p_text.utf8().get_data()); - env->CallVoidMethod(godot_instance, _set_clipboard, jStr); + env->CallVoidMethod(godot_native_bridge, _set_clipboard, jStr); env->DeleteLocalRef(jStr); } } @@ -312,7 +312,7 @@ bool GodotJavaWrapper::has_clipboard() { if (_has_clipboard) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _has_clipboard); + return env->CallBooleanMethod(godot_native_bridge, _has_clipboard); } else { return false; } @@ -330,7 +330,7 @@ Error GodotJavaWrapper::show_dialog(const String &p_title, const String &p_descr env->SetObjectArrayElement(j_buttons, i, j_button); env->DeleteLocalRef(j_button); } - env->CallVoidMethod(godot_instance, _show_dialog, j_title, j_description, j_buttons); + env->CallVoidMethod(godot_native_bridge, _show_dialog, j_title, j_description, j_buttons); env->DeleteLocalRef(j_title); env->DeleteLocalRef(j_description); env->DeleteLocalRef(j_buttons); @@ -347,7 +347,7 @@ Error GodotJavaWrapper::show_input_dialog(const String &p_title, const String &p jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data()); jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data()); jstring jStrExistingText = env->NewStringUTF(p_existing_text.utf8().get_data()); - env->CallVoidMethod(godot_instance, _show_input_dialog, jStrTitle, jStrMessage, jStrExistingText); + env->CallVoidMethod(godot_native_bridge, _show_input_dialog, jStrTitle, jStrMessage, jStrExistingText); env->DeleteLocalRef(jStrTitle); env->DeleteLocalRef(jStrMessage); env->DeleteLocalRef(jStrExistingText); @@ -375,7 +375,7 @@ Error GodotJavaWrapper::show_file_picker(const String &p_current_directory, cons env->SetObjectArrayElement(j_filters, i, j_filter); env->DeleteLocalRef(j_filter); } - env->CallVoidMethod(godot_instance, _show_file_picker, j_current_directory, j_filename, j_mode, j_filters); + env->CallVoidMethod(godot_native_bridge, _show_file_picker, j_current_directory, j_filename, j_mode, j_filters); env->DeleteLocalRef(j_current_directory); env->DeleteLocalRef(j_filename); env->DeleteLocalRef(j_filters); @@ -390,7 +390,7 @@ bool GodotJavaWrapper::request_permission(const String &p_name) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); jstring jStrName = env->NewStringUTF(p_name.utf8().get_data()); - bool result = env->CallBooleanMethod(godot_instance, _request_permission, jStrName); + bool result = env->CallBooleanMethod(godot_native_bridge, _request_permission, jStrName); env->DeleteLocalRef(jStrName); return result; } else { @@ -402,7 +402,7 @@ bool GodotJavaWrapper::request_permissions() { if (_request_permissions) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _request_permissions); + return env->CallBooleanMethod(godot_native_bridge, _request_permissions); } else { return false; } @@ -413,7 +413,7 @@ Vector GodotJavaWrapper::get_granted_permissions() const { if (_get_granted_permissions) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, permissions_list); - jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions); + jobject permissions_object = env->CallObjectMethod(godot_native_bridge, _get_granted_permissions); jobjectArray *arr = reinterpret_cast(&permissions_object); jsize len = env->GetArrayLength(*arr); @@ -432,7 +432,7 @@ Vector GodotJavaWrapper::get_gdextension_list_config_file() const { if (_get_gdextension_list_config_file) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, config_file_list); - jobject config_file_list_object = env->CallObjectMethod(godot_instance, _get_gdextension_list_config_file); + jobject config_file_list_object = env->CallObjectMethod(godot_native_bridge, _get_gdextension_list_config_file); jobjectArray *arr = reinterpret_cast(&config_file_list_object); jsize len = env->GetArrayLength(*arr); @@ -451,7 +451,7 @@ String GodotJavaWrapper::get_ca_certificates() const { if (_get_ca_certificates) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, String()); - jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_ca_certificates); + jstring s = (jstring)env->CallObjectMethod(godot_native_bridge, _get_ca_certificates); ca_certificates = jstring_to_string(s, env); env->DeleteLocalRef(s); } @@ -462,7 +462,7 @@ void GodotJavaWrapper::init_input_devices() { if (_init_input_devices) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _init_input_devices); + env->CallVoidMethod(godot_native_bridge, _init_input_devices); } } @@ -477,7 +477,7 @@ void GodotJavaWrapper::vibrate(int p_duration_ms, float p_amplitude) { j_amplitude = CLAMP(int(p_amplitude * 255), 1, 255); } - env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms, j_amplitude); + env->CallVoidMethod(godot_native_bridge, _vibrate, p_duration_ms, j_amplitude); } } @@ -492,7 +492,7 @@ int GodotJavaWrapper::create_new_godot_instance(const List &args) { env->SetObjectArrayElement(jargs, i, j_arg); env->DeleteLocalRef(j_arg); } - return env->CallIntMethod(godot_instance, _create_new_godot_instance, jargs); + return env->CallIntMethod(godot_native_bridge, _create_new_godot_instance, jargs); } else { return 0; } @@ -504,7 +504,7 @@ void GodotJavaWrapper::begin_benchmark_measure(const String &p_context, const St ERR_FAIL_NULL(env); jstring j_context = env->NewStringUTF(p_context.utf8().get_data()); jstring j_label = env->NewStringUTF(p_label.utf8().get_data()); - env->CallVoidMethod(godot_instance, _begin_benchmark_measure, j_context, j_label); + env->CallVoidMethod(godot_native_bridge, _begin_benchmark_measure, j_context, j_label); env->DeleteLocalRef(j_context); env->DeleteLocalRef(j_label); } @@ -516,7 +516,7 @@ void GodotJavaWrapper::end_benchmark_measure(const String &p_context, const Stri ERR_FAIL_NULL(env); jstring j_context = env->NewStringUTF(p_context.utf8().get_data()); jstring j_label = env->NewStringUTF(p_label.utf8().get_data()); - env->CallVoidMethod(godot_instance, _end_benchmark_measure, j_context, j_label); + env->CallVoidMethod(godot_native_bridge, _end_benchmark_measure, j_context, j_label); env->DeleteLocalRef(j_context); env->DeleteLocalRef(j_label); } @@ -527,7 +527,7 @@ void GodotJavaWrapper::dump_benchmark(const String &benchmark_file) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); jstring j_benchmark_file = env->NewStringUTF(benchmark_file.utf8().get_data()); - env->CallVoidMethod(godot_instance, _dump_benchmark, j_benchmark_file); + env->CallVoidMethod(godot_native_bridge, _dump_benchmark, j_benchmark_file); env->DeleteLocalRef(j_benchmark_file); } } @@ -538,7 +538,7 @@ bool GodotJavaWrapper::check_internal_feature_support(const String &p_feature) c ERR_FAIL_NULL_V(env, false); jstring j_feature = env->NewStringUTF(p_feature.utf8().get_data()); - bool result = env->CallBooleanMethod(godot_instance, _check_internal_feature_support, j_feature); + bool result = env->CallBooleanMethod(godot_native_bridge, _check_internal_feature_support, j_feature); env->DeleteLocalRef(j_feature); return result; } else { @@ -557,7 +557,7 @@ Error GodotJavaWrapper::sign_apk(const String &p_input_path, const String &p_out jstring j_keystore_user = env->NewStringUTF(p_keystore_user.utf8().get_data()); jstring j_keystore_password = env->NewStringUTF(p_keystore_password.utf8().get_data()); - int result = env->CallIntMethod(godot_instance, _sign_apk, j_input_path, j_output_path, j_keystore_path, j_keystore_user, j_keystore_password); + int result = env->CallIntMethod(godot_native_bridge, _sign_apk, j_input_path, j_output_path, j_keystore_path, j_keystore_user, j_keystore_password); env->DeleteLocalRef(j_input_path); env->DeleteLocalRef(j_output_path); @@ -577,7 +577,7 @@ Error GodotJavaWrapper::verify_apk(const String &p_apk_path) { ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED); jstring j_apk_path = env->NewStringUTF(p_apk_path.utf8().get_data()); - int result = env->CallIntMethod(godot_instance, _verify_apk, j_apk_path); + int result = env->CallIntMethod(godot_native_bridge, _verify_apk, j_apk_path); env->DeleteLocalRef(j_apk_path); return static_cast(result); } else { @@ -589,7 +589,7 @@ void GodotJavaWrapper::enable_immersive_mode(bool p_enabled) { if (_enable_immersive_mode) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _enable_immersive_mode, p_enabled); + env->CallVoidMethod(godot_native_bridge, _enable_immersive_mode, p_enabled); } } @@ -597,7 +597,7 @@ bool GodotJavaWrapper::is_in_immersive_mode() { if (_is_in_immersive_mode) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _is_in_immersive_mode); + return env->CallBooleanMethod(godot_native_bridge, _is_in_immersive_mode); } else { return false; } @@ -609,7 +609,7 @@ void GodotJavaWrapper::set_window_color(const Color &p_color) { ERR_FAIL_NULL(env); String color = "#" + p_color.to_html(false); jstring jStrColor = env->NewStringUTF(color.utf8().get_data()); - env->CallVoidMethod(godot_instance, _set_window_color, jStrColor); + env->CallVoidMethod(godot_native_bridge, _set_window_color, jStrColor); } } @@ -619,7 +619,7 @@ void GodotJavaWrapper::on_editor_workspace_selected(const String &p_workspace) { ERR_FAIL_NULL(env); jstring j_workspace = env->NewStringUTF(p_workspace.utf8().get_data()); - env->CallVoidMethod(godot_instance, _on_editor_workspace_selected, j_workspace); + env->CallVoidMethod(godot_native_bridge, _on_editor_workspace_selected, j_workspace); } } @@ -628,7 +628,7 @@ void GodotJavaWrapper::on_distraction_free_mode_changed(bool p_enabled) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _on_distraction_free_mode_changed, p_enabled); + env->CallVoidMethod(godot_native_bridge, _on_distraction_free_mode_changed, p_enabled); } } @@ -638,7 +638,7 @@ bool GodotJavaWrapper::build_env_connect(const Callable &p_callback) { ERR_FAIL_NULL_V(env, false); jobject j_callback = callable_to_jcallable(env, p_callback); - jboolean result = env->CallBooleanMethod(godot_instance, _build_env_connect, j_callback); + jboolean result = env->CallBooleanMethod(godot_native_bridge, _build_env_connect, j_callback); env->DeleteLocalRef(j_callback); return result; @@ -652,7 +652,7 @@ void GodotJavaWrapper::build_env_disconnect() { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _build_env_disconnect); + env->CallVoidMethod(godot_native_bridge, _build_env_disconnect); } } @@ -673,7 +673,7 @@ int GodotJavaWrapper::build_env_execute(const String &p_build_tool, const ListCallIntMethod(godot_instance, _build_env_execute, j_build_tool, j_args, j_project_path, j_gradle_build_directory, j_output_callback, j_result_callback); + jint result = env->CallIntMethod(godot_native_bridge, _build_env_execute, j_build_tool, j_args, j_project_path, j_gradle_build_directory, j_output_callback, j_result_callback); env->DeleteLocalRef(j_build_tool); env->DeleteLocalRef(j_args); @@ -692,7 +692,7 @@ void GodotJavaWrapper::build_env_cancel(int p_job_id) { if (_build_env_cancel) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _build_env_cancel, p_job_id); + env->CallVoidMethod(godot_native_bridge, _build_env_cancel, p_job_id); } } @@ -705,7 +705,7 @@ void GodotJavaWrapper::build_env_clean_project(const String &p_project_path, con jstring j_gradle_build_directory = env->NewStringUTF(p_gradle_build_directory.utf8().get_data()); jobject j_callback = callable_to_jcallable(env, p_callback); - env->CallVoidMethod(godot_instance, _build_env_clean_project, j_project_path, j_gradle_build_directory, j_callback); + env->CallVoidMethod(godot_native_bridge, _build_env_clean_project, j_project_path, j_gradle_build_directory, j_callback); env->DeleteLocalRef(j_project_path); env->DeleteLocalRef(j_gradle_build_directory); @@ -717,7 +717,7 @@ bool GodotJavaWrapper::is_pip_mode_supported() { if (_is_pip_mode_supported) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _is_pip_mode_supported); + return env->CallBooleanMethod(godot_native_bridge, _is_pip_mode_supported); } else { return false; } @@ -727,7 +727,7 @@ bool GodotJavaWrapper::is_in_pip_mode() { if (_is_in_pip_mode) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL_V(env, false); - return env->CallBooleanMethod(godot_instance, _is_in_pip_mode); + return env->CallBooleanMethod(godot_native_bridge, _is_in_pip_mode); } else { return false; } @@ -737,7 +737,7 @@ void GodotJavaWrapper::enter_pip_mode() { if (_enter_pip_mode) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _enter_pip_mode); + env->CallVoidMethod(godot_native_bridge, _enter_pip_mode); } } @@ -745,7 +745,7 @@ void GodotJavaWrapper::set_pip_mode_aspect_ratio(int p_numerator, int p_denomina if (_set_pip_mode_aspect_ratio) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _set_pip_mode_aspect_ratio, p_numerator, p_denominator); + env->CallVoidMethod(godot_native_bridge, _set_pip_mode_aspect_ratio, p_numerator, p_denominator); } } @@ -753,6 +753,6 @@ void GodotJavaWrapper::set_auto_enter_pip_mode_on_background(bool p_auto_enter_o if (_set_auto_enter_pip_mode_on_background) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); - env->CallVoidMethod(godot_instance, _set_auto_enter_pip_mode_on_background, p_auto_enter_on_background); + env->CallVoidMethod(godot_native_bridge, _set_auto_enter_pip_mode_on_background, p_auto_enter_on_background); } } diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 7b56f72e25..b6bb21cb95 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -42,8 +42,8 @@ // Class that makes functions in java/src/org/godotengine/godot/Godot.kt callable from C++ class GodotJavaWrapper { private: - jobject godot_instance; - jclass godot_class; + jobject godot_native_bridge; + jclass godot_native_bridge_class; GodotJavaViewWrapper *godot_view = nullptr; @@ -98,7 +98,7 @@ private: jmethodID _set_auto_enter_pip_mode_on_background = nullptr; public: - GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance); + GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_native_bridge); ~GodotJavaWrapper(); jobject get_activity();