Интегрирование с Android API-ами
Платформа Android имеет множество API, а также богатую экосистему сторонних библиотек с широкими и разнообразными функциональными возможностями, такими как push-уведомления (push notifications), аналитика, аутентификация, реклама (ads) и т. д.
В самом ядре Godot они не имеют смысла, поэтому Godot уже давно предоставляет Android plugin system. Android plugin system позволяет разработчикам создавать плагины Godot для Android с использованием кода Java или Kotlin, предоставляя интерфейс для доступа и использования API Android или сторонних библиотек в проектах Godot из GDScript, C# или GDExtension.
class MyAndroidSingleton(godot: Godot?) : GodotPlugin(godot) {
@UsedByGodot
fun doSomething(value: String) {
// ...
}
}
Однако написание плагина для Android требует знания кода Java или Kotlin, чего большинство разработчиков Godot не знают. Поэтому существует множество API Android и сторонних библиотек, не имеющих плагина Godot, с которым разработчики могли бы взаимодействовать. Фактически, это одна из главных причин, по которой разработчики не могут перейти на Godot с других игровых движков.
Чтобы решить эту проблему, мы представили несколько инструментов в Godot 4.4, которые упрощают для разработчиков процесс доступа к API Android и сторонним библиотекам.
JavaClassWrapper (Godot синглтон)
JavaClassWrapper - это Godot singleton, который позволяет создавать экземпляры классов Java / Kotlin и вызывать их методы, используя только GDScript, C# или GDExtension.
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))
В приведённом выше фрагменте кода JavaClassWrapper используется из GDScript для доступа к классам Java LocalDateTime и DateTimeFormatter. С помощью JavaClassWrapper мы можем вызывать методы классов Java непосредственно из GDScript, как если бы они были методами GDScript.
AndroidRuntime плагин
JavaClassWrapper — это здорово, но для выполнения многих задач на Android вам понадобится доступ к различным объектам Android жизненного цикла/среды выполнения. Плагин AndroidRuntime — это встроенный плагин Godot для Android, который позволяет вам это сделать.
Объединение JavaClassWrapper и плагина AndroidRuntime позволяет разработчикам получать доступ ко множеству API Android и использовать их, не отказываясь от GDScript и не используя какие-либо инструменты, кроме самого Godot. Это огромное преимущество для внедрения Godot в разработку под Android:
Если вам нужно сделать что-то простое или использовать только небольшую часть сторонней библиотеки, вам не обязательно создавать плагин
Это дает разработчикам быстро интегрировать функциональность Android
Позволяет разработчикам создавать дополнения Godot, используя только GDScript и
JavaClassWrapper(Java или Kotlin не требуются)
Примечание
При экспорте с помощью gradle Godot автоматически включает файлы .jar или .aar, найденные в каталоге addons проекта. Поэтому, чтобы использовать стороннюю библиотеку, просто поместите её файл .jar или .aar в каталог addons и вызовите её метод напрямую из GDScript с помощью JavaClassWrapper.
Пример: показ уведомление Android
# 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
Пример: Вызов конструктора
Конструктор вызывается путем вызова метода с тем же именем, что и у класса.
В этом примере создается намерение отправить текст:
# 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)