Merge pull request #117687 from m4gr3d/cleanup_godot_kt

[Android] Clean up `Godot.kt`
This commit is contained in:
Thaddeus Crews
2026-04-08 17:00:38 -05:00
7 changed files with 545 additions and 470 deletions
@@ -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<String> = ArrayList<String>()
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<String>) {
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<String>) {
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<String> {
val configFiles = mutableSetOf<String>()
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<String>): 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<String>, 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)
}
}
}
}
@@ -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.
@@ -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<String>) {
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<String>) {
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<String> {
val configFiles = mutableSetOf<String>()
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<String>): 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<String>,
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)
}
}
}
}
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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);
+105 -105
View File
@@ -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<String> 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<jobjectArray *>(&permissions_object);
jsize len = env->GetArrayLength(*arr);
@@ -432,7 +432,7 @@ Vector<String> 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<jobjectArray *>(&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<String> &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<Error>(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 List<S
jobject j_output_callback = callable_to_jcallable(env, p_output_callback);
jobject j_result_callback = callable_to_jcallable(env, p_result_callback);
jint result = env->CallIntMethod(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);
}
}
+3 -3
View File
@@ -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();