Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
與 Android API 整合
Android 平台擁有眾多 API 與豐富的第三方程式庫生態系,涵蓋推播通知、分析、身份驗證、廣告等各式功能。
這些功能不適合放進 Godot 核心,因此 Godot 早就提供了 Android 外掛系統。Android 外掛系統 讓開發者能以 Java 或 Kotlin 編寫 Godot 的 Android 外掛,並從 GDScript、C# 或 GDExtension 在 Godot 專案中存取與使用 Android API 與第三方程式庫。
class MyAndroidSingleton(godot: Godot?) : GodotPlugin(godot) {
@UsedByGodot
fun doSomething(value: String) {
// ...
}
}
然而撰寫 Android 外掛需要 Java 或 Kotlin 的知識,而多數 Godot 開發者並不具備。因此相當多的 Android API 與第三方程式庫沒有可供對接的 Godot 外掛。事實上,這也是許多開發者無法從其他遊戲引擎轉用 Godot 的主因之一。
為了解決這個問題,我們在 Godot 4.4 引入了幾個工具,簡化開發者存取 Android API 與第三方程式庫的流程。
JavaClassWrapper(Godot 單例)
JavaClassWrapper 是一個 Godot 單例,讓你僅用 GDScript、C# 或 GDExtension 就能建立 Java / Kotlin 類別的實例並呼叫其方法。
var LocalDateTime = JavaClassWrapper.wrap("java.time.LocalDateTime")
var DateTimeFormatter = JavaClassWrapper.wrap("java.time.format.DateTimeFormatter")
var datetime = LocalDateTime.now()
var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss")
print(datetime.format(formatter))
在上述程式碼片段中,透過 GDScript 使用 JavaClassWrapper 來存取 Java 的 LocalDateTime 與 DateTimeFormatter 類別。透過 JavaClassWrapper,我們可以像呼叫 GDScript 方法一樣,直接從 GDScript 呼叫這些 Java 類別的方法。
AndroidRuntime 外掛
JavaClassWrapper 很強大,但在 Android 上做許多事情需要存取各種生命週期/執行期物件。AndroidRuntime 外掛是 Godot 內建的 Android 外掛,可滿足這些需求。
結合 JavaClassWrapper 與 AndroidRuntime 外掛, 開發者無需離開 GDScript, 也不需要 Godot 以外的工具, 就能存取並使用 Android API。這對推廣以 Godot 進行 Android 開發而言影響 重大 :
如果你只需要做些簡單的事,或只用到第三方程式庫的一小部分,就不必製作外掛
它讓開發者能快速整合 Android 功能
它讓開發者僅用 GDScript 與
JavaClassWrapper就能打造 Godot 外掛(不需要 Java 或 Kotlin)
備註
對於使用 gradle 的匯出,Godot 會自動納入在專案 addons 目錄中找到的 .jar 或 .aar 檔案。因此要使用第三方程式庫,只需把其 .jar 或 .aar 檔放進 addons 目錄,並透過 JavaClassWrapper 直接在 GDScript 中呼叫其方法即可。
範例:顯示 Android toast
# Retrieve the AndroidRuntime singleton.
var android_runtime = Engine.get_singleton("AndroidRuntime")
if android_runtime:
# Retrieve the Android Activity instance.
var activity = android_runtime.getActivity()
# Create a Godot Callable to wrap the toast display logic.
var toast_callable = func():
# Use JavaClassWrapper to retrieve the android.widget.Toast class, then make and show a toast using the class APIs.
var ToastClass = JavaClassWrapper.wrap("android.widget.Toast")
ToastClass.makeText(activity, "This is a test", ToastClass.LENGTH_LONG).show()
# Wrap the Callable in a Java Runnable and run it on the Android UI thread to show the toast.
activity.runOnUiThread(android_runtime.createRunnableFromGodotCallable(toast_callable))
範例:讓裝置震動
# Retrieve the AndroidRuntime singleton.
var android_runtime = Engine.get_singleton("AndroidRuntime")
if android_runtime:
# Retrieve the Android Vibrator system service and check if the device supports it.
var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
if vibrator_service and vibrator_service.hasVibrator():
# Configure and run a VibrationEffect.
var VibrationEffect = JavaClassWrapper.wrap("android.os.VibrationEffect")
var effect = VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE)
vibrator_service.vibrate(effect)
範例:存取內部類別
Java 的內部類別可使用 $ 符號來存取:
# Accessing 'VERSION' class, which is an inner class from the 'android.os.Build' class.
var version = JavaClassWrapper.wrap("android.os.Build$VERSION")
var sdk_int = version.SDK_INT
if sdk_int == 30:
# Do something specific on android 11 devices.
else:
# All other devices
範例:呼叫建構函式
建構函式是以與類別同名的方法來呼叫的。
此範例會建立一個用來傳送文字的 intent:
# Retrieve the AndroidRuntime singleton.
var android_runtime = Engine.get_singleton("AndroidRuntime")
if android_runtime:
var Intent = JavaClassWrapper.wrap("android.content.Intent")
var activity = android_runtime.getActivity()
var intent = Intent.Intent() # Call the constructor.
intent.setAction(Intent.ACTION_SEND)
intent.putExtra(Intent.EXTRA_TEXT, "This is a test message.")
intent.setType("text/plain")
activity.startActivity(intent)
Example: Saving an image to the Android gallery
# Retrieve the AndroidRuntime singleton.
var android_runtime = Engine.get_singleton("AndroidRuntime")
if android_runtime:
var Intent = JavaClassWrapper.wrap("android.content.Intent")
var activity = android_runtime.getActivity()
var intent = Intent.Intent()
# Create the File and Uri.
var Uri = JavaClassWrapper.wrap("android.net.Uri")
var File = JavaClassWrapper.wrap("java.io.File")
var file = File.File(file_path_to_image_here)
var uri = Uri.fromFile(file)
# Set Action and Data of Intent.
intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
intent.setData(uri)
# Broadcast it.
activity.sendBroadcast(intent)