diff options
Diffstat (limited to 'platform/android/java')
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); } } |