summaryrefslogtreecommitdiffstats
path: root/platform/android/java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/java')
-rw-r--r--platform/android/java/editor/src/.gitignore1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt13
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java131
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java72
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java31
5 files changed, 90 insertions, 158 deletions
diff --git a/platform/android/java/editor/src/.gitignore b/platform/android/java/editor/src/.gitignore
new file mode 100644
index 0000000000..c081ec3425
--- /dev/null
+++ b/platform/android/java/editor/src/.gitignore
@@ -0,0 +1 @@
+!/debug
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
index 9c1165bf8a..e115494cfd 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -907,6 +907,19 @@ class Godot(private val context: Context) : SensorEventListener {
return PermissionsUtil.getGrantedPermissions(getActivity())
}
+ /**
+ * 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()
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
index 48aa231c7a..7f3a3ac7a3 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
@@ -57,27 +57,28 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
- * Base class for the Godot Android plugins.
+ * Base class for Godot Android plugins.
* <p>
- * A Godot Android plugin is a regular Android library packaged as an aar archive file with the following caveats:
+ * A Godot Android plugin is an Android library with the following requirements:
* <p>
- * - The library must have a dependency on the Godot Android library (godot-lib.aar).
- * A stable version is available for each release.
+ * - The plugin must have a dependency on the Godot Android library: `implementation "org.godotengine:godot:<godotLibVersion>"`
+ * <p>
+ * - The plugin must include a <meta-data> tag in its Android manifest with the following format:
+ * <meta-data android:name="org.godotengine.plugin.v2.[PluginName]" android:value="[plugin.init.ClassFullName]" />
* <p>
- * - The library must include a <meta-data> tag in its manifest file setup as follow:
- * <meta-data android:name="org.godotengine.plugin.v1.[PluginName]" android:value="[plugin.init.ClassFullName]" />
* Where:
+ * <p>
* - 'PluginName' is the name of the plugin.
- * - 'plugin.init.ClassFullName' is the full name (package + class name) of the plugin class
+ * <p>
+ * - 'plugin.init.ClassFullName' is the full name (package + class name) of the plugin init class
* extending {@link GodotPlugin}.
+ * <p>
+ * A Godot Android plugin can also define and provide c/c++ gdextension libraries, which will be
+ * automatically bundled by the aar build system.
+ * GDExtension ('*.gdextension') config files must be located in the project 'assets' directory and
+ * their paths specified by {@link GodotPlugin#getPluginGDExtensionLibrariesPaths()}.
*
- * A plugin can also define and provide c/c++ gdextension libraries and nativescripts for the target
- * app/game to leverage.
- * The shared library for the gdextension library will be automatically bundled by the aar build
- * system.
- * Godot '*.gdextension' resource files must however be manually defined in the project
- * 'assets' directory. The recommended path for these resources in the 'assets' directory should be:
- * 'godot/plugin/v1/[PluginName]/'
+ * @see <a href="https://docs.godotengine.org/en/stable/tutorials/platform/android/index.html">Android plugins</a>
*/
public abstract class GodotPlugin {
private static final String TAG = GodotPlugin.class.getSimpleName();
@@ -85,6 +86,10 @@ public abstract class GodotPlugin {
private final Godot godot;
private final ConcurrentHashMap<String, SignalInfo> registeredSignals = new ConcurrentHashMap<>();
+ /**
+ * Base constructor passing a {@link Godot} instance through which the plugin can access Godot's
+ * APIs and lifecycle events.
+ */
public GodotPlugin(Godot godot) {
this.godot = godot;
}
@@ -97,7 +102,7 @@ public abstract class GodotPlugin {
}
/**
- * Provides access to the underlying {@link Activity}.
+ * Provides access to the hosting {@link Activity}.
*/
@Nullable
protected Activity getActivity() {
@@ -106,33 +111,16 @@ public abstract class GodotPlugin {
/**
* Register the plugin with Godot native code.
- *
- * This method is invoked on the render thread.
+ * <p>
+ * This method is invoked by the Godot Engine on the render thread.
*/
public final void onRegisterPluginWithGodotNative() {
registeredSignals.putAll(
- registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
- getPluginGDExtensionLibrariesPaths()));
- }
-
- /**
- * Register the plugin with Godot native code.
- *
- * This method must be invoked on the render thread.
- */
- public static void registerPluginWithGodotNative(Object pluginObject,
- GodotPluginInfoProvider pluginInfoProvider) {
- registerPluginWithGodotNative(pluginObject, pluginInfoProvider.getPluginName(),
- Collections.emptyList(), pluginInfoProvider.getPluginSignals(),
- pluginInfoProvider.getPluginGDExtensionLibrariesPaths());
-
- // Notify that registration is complete.
- pluginInfoProvider.onPluginRegistered();
+ registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals()));
}
private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
- String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals,
- Set<String> pluginGDExtensionLibrariesPaths) {
+ String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals) {
nativeRegisterSingleton(pluginName, pluginObject);
Set<Method> filteredMethods = new HashSet<>();
@@ -176,23 +164,18 @@ public abstract class GodotPlugin {
registeredSignals.put(signalName, signalInfo);
}
- // Get the list of gdextension libraries to register.
- if (!pluginGDExtensionLibrariesPaths.isEmpty()) {
- nativeRegisterGDExtensionLibraries(pluginGDExtensionLibrariesPaths.toArray(new String[0]));
- }
-
return registeredSignals;
}
/**
- * Invoked once during the Godot Android initialization process after creation of the
+ * Invoked once during the initialization process after creation of the
* {@link org.godotengine.godot.GodotRenderView} view.
* <p>
- * The plugin can return a non-null {@link View} layout in order to add it to the Godot view
+ * The plugin can return a non-null {@link View} layout which will be added to the Godot view
* hierarchy.
- *
- * Use shouldBeOnTop() to set whether the plugin's {@link View} should be added on top or behind
- * the main Godot view.
+ * <p>
+ * Use {@link GodotPlugin#shouldBeOnTop()} to specify whether the plugin's {@link View} should
+ * be added on top or behind the main Godot view.
*
* @see Activity#onCreate(Bundle)
* @return the plugin's view to be included; null if no views should be included.
@@ -235,44 +218,52 @@ public abstract class GodotPlugin {
public boolean onMainBackPressed() { return false; }
/**
- * Invoked on the render thread when the Godot setup is complete.
+ * Invoked on the render thread when set up of the Godot engine is complete.
+ * <p>
+ * This is invoked before {@link GodotPlugin#onGodotMainLoopStarted()}.
*/
public void onGodotSetupCompleted() {}
/**
* Invoked on the render thread when the Godot main loop has started.
+ *
+ * This is invoked after {@link GodotPlugin#onGodotSetupCompleted()}.
*/
public void onGodotMainLoopStarted() {}
/**
- * Invoked once per frame on the GL thread after the frame is drawn.
+ * When using the OpenGL renderer, this is invoked once per frame on the GL thread after the
+ * frame is drawn.
*/
public void onGLDrawFrame(GL10 gl) {}
/**
- * Called on the GL thread after the surface is created and whenever the OpenGL ES surface size
- * changes.
+ * When using the OpenGL renderer, this is called on the GL thread after the surface is created
+ * and whenever the OpenGL ES surface size changes.
*/
public void onGLSurfaceChanged(GL10 gl, int width, int height) {}
/**
- * Called on the GL thread when the surface is created or recreated.
+ * When using the OpenGL renderer, this is called on the GL thread when the surface is created
+ * or recreated.
*/
public void onGLSurfaceCreated(GL10 gl, EGLConfig config) {}
/**
- * Invoked once per frame on the Vulkan thread after the frame is drawn.
+ * When using the Vulkan renderer, this is invoked once per frame on the Vulkan thread after
+ * the frame is drawn.
*/
public void onVkDrawFrame() {}
/**
- * Called on the Vulkan thread after the surface is created and whenever the surface size
- * changes.
+ * When using the Vulkan renderer, this is called on the Vulkan thread after the surface is
+ * created and whenever the surface size changes.
*/
public void onVkSurfaceChanged(Surface surface, int width, int height) {}
/**
- * Called on the Vulkan thread when the surface is created or recreated.
+ * When using the Vulkan renderer, this is called on the Vulkan thread when the surface is
+ * created or recreated.
*/
public void onVkSurfaceCreated(Surface surface) {}
@@ -287,7 +278,7 @@ public abstract class GodotPlugin {
/**
* Returns the list of methods to be exposed to Godot.
*
- * @deprecated Used the {@link UsedByGodot} annotation instead.
+ * @deprecated Use the {@link UsedByGodot} annotation instead.
*/
@NonNull
@Deprecated
@@ -304,19 +295,19 @@ public abstract class GodotPlugin {
}
/**
- * Returns the paths for the plugin's gdextension libraries.
- *
- * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
+ * Returns the paths for the plugin's gdextension libraries (if any).
+ * <p>
+ * Each returned path must be relative to the 'assets' directory and point to a '*.gdextension' file.
*/
@NonNull
- protected Set<String> getPluginGDExtensionLibrariesPaths() {
+ public Set<String> getPluginGDExtensionLibrariesPaths() {
return Collections.emptySet();
}
/**
- * Returns whether the plugin's {@link View} returned in onMainCreate() should be placed on
- * top of the main Godot view.
- *
+ * Returns whether the plugin's {@link View} returned in
+ * {@link GodotPlugin#onMainCreate(Activity)} should be placed on top of the main Godot view.
+ * <p>
* Returning false causes the plugin's {@link View} to be placed behind, which can be useful
* when used with transparency in order to let the Godot view handle inputs.
*/
@@ -359,7 +350,7 @@ public abstract class GodotPlugin {
}
emitSignal(getGodot(), getPluginName(), signalInfo, signalArgs);
} catch (IllegalArgumentException exception) {
- Log.w(TAG, exception.getMessage());
+ Log.w(TAG, exception);
if (BuildConfig.DEBUG) {
throw exception;
}
@@ -368,7 +359,7 @@ public abstract class GodotPlugin {
/**
* Emit a Godot signal.
- * @param godot
+ * @param godot Godot instance
* @param pluginName Name of the Godot plugin the signal will be emitted from. The plugin must already be registered with the Godot engine.
* @param signalInfo Information about the signal to emit.
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the given {@link SignalInfo} parameter.
@@ -397,7 +388,7 @@ public abstract class GodotPlugin {
godot.runOnRenderThread(() -> nativeEmitSignal(pluginName, signalInfo.getName(), signalArgs));
} catch (IllegalArgumentException exception) {
- Log.w(TAG, exception.getMessage());
+ Log.w(TAG, exception);
if (BuildConfig.DEBUG) {
throw exception;
}
@@ -420,13 +411,7 @@ public abstract class GodotPlugin {
private static native void nativeRegisterMethod(String p_sname, String p_name, String p_ret, String[] p_params);
/**
- * Used to register gdextension libraries bundled by the plugin.
- * @param gdextensionPaths Paths to the libraries relative to the 'assets' directory.
- */
- private static native void nativeRegisterGDExtensionLibraries(String[] gdextensionPaths);
-
- /**
- * Used to complete registration of the {@link GodotPlugin} instance's methods.
+ * Used to complete registration of the {@link GodotPlugin} instance's signals.
* @param pluginName Name of the plugin
* @param signalName Name of the signal to register
* @param signalParamTypes Signal parameters types
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
deleted file mode 100644
index 63999a8321..0000000000
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginInfoProvider.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**************************************************************************/
-/* GodotPluginInfoProvider.java */
-/**************************************************************************/
-/* 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.plugin;
-
-import androidx.annotation.NonNull;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Provides the set of information expected from a Godot plugin.
- */
-public interface GodotPluginInfoProvider {
- /**
- * Returns the name of the plugin.
- */
- @NonNull
- String getPluginName();
-
- /**
- * Returns the list of signals to be exposed to Godot.
- */
- @NonNull
- default Set<SignalInfo> getPluginSignals() {
- return Collections.emptySet();
- }
-
- /**
- * Returns the paths for the plugin's gdextension libraries (if any).
- *
- * The paths must be relative to the 'assets' directory and point to a '*.gdextension' file.
- */
- @NonNull
- default Set<String> getPluginGDExtensionLibrariesPaths() {
- return Collections.emptySet();
- }
-
- /**
- * This is invoked on the render thread when the plugin described by this instance has been
- * registered.
- */
- default void onPluginRegistered() {
- }
-}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
index c2428de2e1..d338b72441 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
@@ -52,7 +52,14 @@ import java.util.concurrent.ConcurrentHashMap;
public final class GodotPluginRegistry {
private static final String TAG = GodotPluginRegistry.class.getSimpleName();
+ /**
+ * Prefix used for version 1 of the Godot plugin, mostly compatible with Godot 3.x
+ */
private static final String GODOT_PLUGIN_V1_NAME_PREFIX = "org.godotengine.plugin.v1.";
+ /**
+ * Prefix used for version 2 of the Godot plugin, compatible with Godot 4.2+
+ */
+ private static final String GODOT_PLUGIN_V2_NAME_PREFIX = "org.godotengine.plugin.v2.";
private static GodotPluginRegistry instance;
private final ConcurrentHashMap<String, GodotPlugin> registry;
@@ -123,11 +130,17 @@ public final class GodotPluginRegistry {
return;
}
- int godotPluginV1NamePrefixLength = GODOT_PLUGIN_V1_NAME_PREFIX.length();
for (String metaDataName : metaData.keySet()) {
// Parse the meta-data looking for entry with the Godot plugin name prefix.
- if (metaDataName.startsWith(GODOT_PLUGIN_V1_NAME_PREFIX)) {
- String pluginName = metaDataName.substring(godotPluginV1NamePrefixLength).trim();
+ String pluginName = null;
+ if (metaDataName.startsWith(GODOT_PLUGIN_V2_NAME_PREFIX)) {
+ pluginName = metaDataName.substring(GODOT_PLUGIN_V2_NAME_PREFIX.length()).trim();
+ } else if (metaDataName.startsWith(GODOT_PLUGIN_V1_NAME_PREFIX)) {
+ pluginName = metaDataName.substring(GODOT_PLUGIN_V1_NAME_PREFIX.length()).trim();
+ Log.w(TAG, "Godot v1 plugin are deprecated in Godot 4.2 and higher: " + pluginName);
+ }
+
+ if (!TextUtils.isEmpty(pluginName)) {
Log.i(TAG, "Initializing Godot plugin " + pluginName);
// Retrieve the plugin class full name.
@@ -149,15 +162,7 @@ public final class GodotPluginRegistry {
}
registry.put(pluginName, pluginHandle);
Log.i(TAG, "Completed initialization for Godot plugin " + pluginHandle.getPluginName());
- } catch (ClassNotFoundException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (IllegalAccessException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (InstantiationException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (NoSuchMethodException e) {
- Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
- } catch (InvocationTargetException e) {
+ } catch (Exception e) {
Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
}
} else {
@@ -165,7 +170,7 @@ public final class GodotPluginRegistry {
}
}
}
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (Exception e) {
Log.e(TAG, "Unable load Godot Android plugins from the manifest file.", e);
}
}