Godot Android 插件
前言
Android plugins are powerful tools to extend the capabilities of the Godot engine by tapping into the functionality provided by Android platforms and ecosystem.
For example in Godot 4, Android plugins are used to support multiple Android-based XR platforms without encumbering the core codebase with vendor specific code or binaries.
Android 插件
Android 插件系统的第一版(v1)是在 Godot 3 中引入的,与 Godot 4.0 和 4.1 兼容。这个版本能够让开发者使用 Java、Kotlin 和原生功能增强 Godot 引擎。
从 Godot 4.2 开始,废弃了使用 v1 架构构建的 Android 插件。Godot 4.2 为 Android 插件引入了全新的第二版(v2)架构。
v2 架构
备注
Godot Android 插件使用 Gradle 构建系统。
与之前的 v1 架构一样,Android 插件仍然是基于 Android 归档库的。
Godot Android 插件 v2 的本质仍然是一个 Android 库,依赖于 Godot Android 库和自定义的 Android 库说明文件。
这个架构能够让 Android 插件通过以下方法扩展功能:
Android 平台 API
Android 库
Kotlin 和 Java 库
原生库(通过 JNI)
GDExtension 库
Each plugin has an init class extending from the GodotPlugin class which is provided by the Godot Android library.
The GodotPlugin
class provides APIs to access the running Godot instance and hook into its lifecycle. It is loaded at runtime by the Godot engine.
v2 打包格式
v1 Android plugins required a custom gdap
configuration file that was used by the Godot Editor to detect and load them. However this approach had several drawbacks, primary ones being that it lacked flexibility and departed from the existing Godot EditorExportPlugin format, delivery and installation flow.
This has been resolved for v2 Android plugins by deprecating the gdap
packaging and configuration mechanism in favor of the existing Godot EditorExportPlugin
packaging format. The EditorExportPlugin
API in turn has been extended to properly support Android plugins.
构建 v2 Android 插件
A github project template is provided at https://github.com/m4gr3d/Godot-Android-Plugin-Template as a quickstart for building Godot Android plugins for Godot 4.2+. You can follow the template README to set up your own Godot Android plugin project.
To provide further understanding, here is a break-down of the steps used to create the project template:
按照 这些说明 创建一个Android库模块。
Add the Godot Android library as a dependency by updating the module’s
gradle
build file:dependencies {
implementation("org.godotengine:godot:4.2.0.stable")
}
The Godot Android library is hosted on MavenCentral, and updated for each release.
Create GodotAndroidPlugin, an init class for the plugin extending GodotPlugin.
If the plugin exposes Kotlin or Java methods to be called from GDScript, they must be annotated with @UsedByGodot. The name called from GDScript must match the method name exactly. There is no coercing
snake_case
tocamelCase
. For example, from GDScript:if Engine.has_singleton("MyPlugin"):
var singleton = Engine.get_singleton("MyPlugin")
print(singleton.myPluginFunction("World"))
If the plugin uses signals, the init class must return the set of signals used by overriding GodotPlugin::getPluginSignals(). To emit signals, the plugin can use the GodotPlugin::emitSignal(…) method.
Update the plugin
AndroidManifest.xml
file with the following meta-data:<meta-data
android:name="org.godotengine.plugin.v2.[PluginName]"
android:value="[plugin.init.ClassFullName]" />
Where:
PluginName
is the name of the plugin
plugin.init.ClassFullName
is the full component name (package + class name) of the plugin init class (e.g:org.godotengine.plugin.android.template.GodotAndroidPlugin
).
- Create the EditorExportPlugin configuration to package the plugin. The steps used to create the configuration can be seen in the Packaging a v2 Android plugin section.
构建带 GDExtension 能力的 v2 Android 插件
Similar to GDNative support in v1 Android plugins, v2 Android plugins support the ability to integrate GDExtension capabilities.
A github project template is provided at https://github.com/m4gr3d/GDExtension-Android-Plugin-Template as a quickstart for building GDExtension Android plugins for Godot 4.2+. You can follow the template’s README to set up your own Godot Android plugin project.
Migrating a v1 Android plugin to v2
Use the following steps if you have a v1 Android plugin you want to migrate to v2:
Update the plugin’s manifest file:
- Change the
org.godotengine.plugin.v1
prefix toorg.godotengine.plugin.v2
- Change the
Update the Godot Android library build dependency:
You can continue using the
godot-lib.<version>.<status>.aar
binary from Godot’s download page if that’s your preference. Make sure it’s updated to the latest stable version.Or you can switch to the MavenCentral provided dependency:
dependencies {
implementation("org.godotengine:godot:4.2.0.stable")
}
After updating the Godot Android library dependency, sync or build the plugin and resolve any compile errors:
- The
Godot
instance provided byGodotPlugin::getGodot()
no longer has access to aandroid.content.Context
reference. UseGodotPlugin::getActivity()
instead.
- The
Delete the
gdap
configuration file(s) and follow the instructions in the Packaging a v2 Android plugin section to set up the plugin configuration.
打包 v2 Android 插件
如前文所述,v2 版本的 Android 插件现在是以 EditorExportPlugin
插件的形式提供给 Godot 编辑器的,所以打包方法也大致相同。
在插件目录(例如
addons/<插件名称>/
)中添加插件输出的二进制文件在插件目录(例如
addons/<插件名称>/
)中添加实现导出功能的工具脚本创建的脚本必须是
@tool
脚本,否则无法正常工作导出工具脚本的作用是对 Android 插件进行配置,并将其加入 Godot 编辑器的导出流程。这个脚本大致应该是这样的:
``` @tool extends EditorPlugin
A class member to hold the editor export plugin during its lifecycle.
var export_plugin : AndroidExportPlugin
func _enter_tree():
# Initialization of the plugin goes here.
export_plugin = AndroidExportPlugin.new()
add_export_plugin(export_plugin)
func _exit_tree():
# Clean-up of the plugin goes here.
remove_export_plugin(export_plugin)
export_plugin = null
class AndroidExportPlugin extends EditorExportPlugin:
# Plugin's name.
var _plugin_name = "<plugin_name>"
# Specifies which platform is supported by the plugin.
func _supports_platform(platform):
if platform is EditorExportPlatformAndroid:
return true
return false
# Return the paths of the plugin's AAR binaries relative to the 'addons' directory.
func _get_android_libraries(platform, debug):
if debug:
return PackedStringArray(["<paths_to_debug_android_plugin_aar_binaries>"])
else:
return PackedStringArray(["<paths_to_release_android_plugin_aar_binaries>"])
# Return the plugin's name.
func _get_name():
return _plugin_name
```
这个工具脚本中最常用的 EditorExportPlugin API 如下:
_supports_platform: returns
true
if the plugin supports the given platform. For Android plugins, this must returntrue
whenplatform
is EditorExportPlatformAndroid_get_android_libraries: retrieve the local paths of the Android libraries binaries (AAR files) provided by the plugin
_get_android_dependencies: retrieve the set of Android maven dependencies (e.g: org.godot.example:my-plugin:0.0.0) provided by the plugin
_get_android_dependencies_maven_repos: retrieve the urls of the maven repos for the android dependencies provided by
_get_android_dependencies
_get_android_manifest_activity_element_contents: update the contents of the <activity> element in the generated Android manifest
_get_android_manifest_application_element_contents: update the contents of the <application> element in the generated Android manifest
_get_android_manifest_element_contents: update the contents of the <manifest> element in the generated Android manifest
The
_get_android_manifest_*
methods allow the plugin to automatically provide changes to the app’s manifest which are preserved when the Godot Editor is updated, resolving a long standing issue with v1 Android plugins.
Create a
plugin.cfg
. This is an INI file with metadata about your plugin:[plugin]
name="<plugin_name>"
description="<plugin_description>"
author="<plugin_author>"
version="<plugin_version>"
script="<relative_path_to_the_export_tool_script>"
For reference, here is the folder structure for the Godot Android plugin project template. At build time, the contents of the export_scripts_template
directory as well as the generated plugin binaries are copied to the addons/<plugin_name>
directory:
export_scripts_template/
|
+--export_plugin.gd # export plugin tool script
|
+--plugin.cfg # plugin INI file
Packaging a v2 Android plugin with GDExtension capabilities
For GDExtension, we follow the same steps as for Packaging a v2 Android plugin and add the GDExtension config file in the same location as plugin.cfg
.
For reference, here is the folder structure for the GDExtension Android plugin project template. At build time, the contents of the export_scripts_template
directory as well as the generated plugin binaries are copied to the addons/<plugin_name>
directory:
export_scripts_template/
|
+--export_plugin.gd # export plugin tool script
|
+--plugin.cfg # plugin INI file
|
+--plugin.gdextension # GDExtension config file
配置文件 plugin.gdextension
看上去是这样的:
[configuration]
entry_symbol = "plugin_library_init"
compatibility_minimum = "4.2"
android_aar_plugin = true
[libraries]
android.debug.arm64 = "res://addons/GDExtensionAndroidPluginTemplate/bin/debug/arm64-v8a/libGDExtensionAndroidPluginTemplate.so"
android.release.arm64 = "res://addons/GDExtensionAndroidPluginTemplate/bin/release/arm64-v8a/libGDExtensionAndroidPluginTemplate.so"
...
需要注意的是这里的 android_aar_plugin
字段,这个字段说明该 GDExtension 模块是以 v2 Android 插件的形式提供的。导出过程中就会告诉 Godot 编辑器,这个 GDExtension 原生共享库是由 Android 插件 AAR 二进制导出的。
对 GDExtension Android 插件而言,插件的初始类必须覆盖 GodotPlugin::getPluginGDExtensionLibrariesPaths(),并且返回所捆绑的 GDExtension 库配置文件的路径(*.gdextension
)。
路径必须相对于 Android 库的 assets
目录。运行时,插件会向 Godot 引擎提供这些路径,用于加载并初始化所捆绑的 GDExtension 库。
使用 v2 Android 插件
备注
要求 Godot 4.2 或更高版本
v2 Android plugin requires the use of the Gradle build process.
The provided github project templates include demo Godot projects for quick testing.
Copy the plugin’s output directory (
addons/<plugin_name>
) to the target Godot project’s directoryOpen the project in the Godot Editor; the Editor should detect the plugin
导航到
项目
->项目设置...
->插件
,并确保插件已启用Install the Godot Android build template by clicking on
Project
->Install Android Build Template...
Navigate to
Project
->Export...
In the
Export
window, create anAndroid export preset
In the
Android export preset
, scroll toGradle Build
and setUse Gradle Build
totrue
Update the project’s scripts as needed to access the plugin’s functionality. For example:
if Engine.has_singleton("MyPlugin"):
var singleton = Engine.get_singleton("MyPlugin")
print(singleton.myPluginFunction("World"))
Connect an Android device to your machine and run the project on it
Using a v2 Android plugin as an Android library
Since they are also Android libraries, Godot v2 Android plugins can be stripped from their EditorExportPlugin
packaging and provided as raw AAR
binaries for use as libraries alongside the Godot Android library by Android apps.
If targeting this use-case, make sure to include additional instructions for how the AAR
binaries should be included (e.g: custom additions to the Android app’s manifest).
参考实现
技巧与指南
简化对暴露的 Java / Kotlin API 的访问
To make it easier to access the exposed Java / Kotlin APIs in the Godot Editor, it’s recommended to provide one (or multiple) gdscript wrapper class(es) for your plugin users to interface with.
例如:
class_name PluginInterface extends Object
## Interface used to access the functionality provided by this plugin.
var _plugin_name = "GDExtensionAndroidPluginTemplate"
var _plugin_singleton
func _init():
if Engine.has_singleton(_plugin_name):
_plugin_singleton = Engine.get_singleton(_plugin_name)
else:
printerr("Initialization error: unable to access the java logic")
## Print a 'Hello World' message to the logcat.
func helloWorld():
if _plugin_singleton:
_plugin_singleton.helloWorld()
else:
printerr("Initialization error")
Support using the GDExtension functionality in the Godot Editor
If planning to use the GDExtension functionality in the Godot Editor, it is recommended that the GDExtension’s native binaries are compiled not just for Android, but also for the OS onto which developers / users intend to run the Godot Editor. Not doing so may prevent developers / users from writing code that accesses the plugin from within the Godot Editor.
This may involve creating dummy plugins for the host OS just so the API is published to the editor. You can use the godot-cpp-template github template for reference on how to do so.
Godot 在加载时崩溃
检查 adb logcat
是否存在可能的问题,然后:
检查插件暴露的方法是否使用了下列 Java 类型:
void
、boolean
、int
、float
、java.lang.String
、org.godotengine.godot.Dictionary
、int[]
、byte[]
、float[]
、java.lang.String[]
。暂时不支持更复杂的数据类型.