You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Fix leakage of JNI object references
Fixes https://github.com/godotengine/godot/issues/87548
This commit is contained in:
@@ -36,7 +36,6 @@
|
|||||||
#include "os_android.h"
|
#include "os_android.h"
|
||||||
#include "thread_jandroid.h"
|
#include "thread_jandroid.h"
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
#include <openxr/openxr_platform.h>
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
@@ -48,6 +47,12 @@ OpenXRAndroidExtension *OpenXRAndroidExtension::get_singleton() {
|
|||||||
|
|
||||||
OpenXRAndroidExtension::OpenXRAndroidExtension() {
|
OpenXRAndroidExtension::OpenXRAndroidExtension() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
|
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->GetJavaVM(&vm);
|
||||||
|
activity_object = env->NewGlobalRef(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());
|
||||||
}
|
}
|
||||||
|
|
||||||
HashMap<String, bool *> OpenXRAndroidExtension::get_requested_extensions() {
|
HashMap<String, bool *> OpenXRAndroidExtension::get_requested_extensions() {
|
||||||
@@ -66,11 +71,6 @@ void OpenXRAndroidExtension::on_before_instance_created() {
|
|||||||
}
|
}
|
||||||
loader_init_extension_available = true;
|
loader_init_extension_available = true;
|
||||||
|
|
||||||
JNIEnv *env = get_jni_env();
|
|
||||||
JavaVM *vm;
|
|
||||||
env->GetJavaVM(&vm);
|
|
||||||
jobject activity_object = env->NewGlobalRef(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());
|
|
||||||
|
|
||||||
XrLoaderInitInfoAndroidKHR loader_init_info_android = {
|
XrLoaderInitInfoAndroidKHR loader_init_info_android = {
|
||||||
.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR,
|
.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR,
|
||||||
.next = nullptr,
|
.next = nullptr,
|
||||||
@@ -93,11 +93,6 @@ void *OpenXRAndroidExtension::set_instance_create_info_and_get_next_pointer(void
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEnv *env = get_jni_env();
|
|
||||||
JavaVM *vm;
|
|
||||||
env->GetJavaVM(&vm);
|
|
||||||
jobject activity_object = env->NewGlobalRef(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());
|
|
||||||
|
|
||||||
instance_create_info = {
|
instance_create_info = {
|
||||||
.type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR,
|
.type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR,
|
||||||
.next = p_next_pointer,
|
.next = p_next_pointer,
|
||||||
@@ -109,4 +104,9 @@ void *OpenXRAndroidExtension::set_instance_create_info_and_get_next_pointer(void
|
|||||||
|
|
||||||
OpenXRAndroidExtension::~OpenXRAndroidExtension() {
|
OpenXRAndroidExtension::~OpenXRAndroidExtension() {
|
||||||
singleton = nullptr;
|
singleton = nullptr;
|
||||||
|
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(activity_object);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
#include "../../util.h"
|
#include "../../util.h"
|
||||||
#include "../openxr_extension_wrapper.h"
|
#include "../openxr_extension_wrapper.h"
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
class OpenXRAndroidExtension : public OpenXRExtensionWrapper {
|
class OpenXRAndroidExtension : public OpenXRExtensionWrapper {
|
||||||
public:
|
public:
|
||||||
static OpenXRAndroidExtension *get_singleton();
|
static OpenXRAndroidExtension *get_singleton();
|
||||||
@@ -49,6 +51,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static OpenXRAndroidExtension *singleton;
|
static OpenXRAndroidExtension *singleton;
|
||||||
|
|
||||||
|
JavaVM *vm;
|
||||||
|
jobject activity_object;
|
||||||
bool loader_init_extension_available = false;
|
bool loader_init_extension_available = false;
|
||||||
bool create_instance_extension_available = false;
|
bool create_instance_extension_available = false;
|
||||||
|
|
||||||
|
|||||||
@@ -209,8 +209,6 @@ class JavaClassWrapper : public Object {
|
|||||||
#ifdef ANDROID_ENABLED
|
#ifdef ANDROID_ENABLED
|
||||||
RBMap<String, Ref<JavaClass>> class_cache;
|
RBMap<String, Ref<JavaClass>> class_cache;
|
||||||
friend class JavaClass;
|
friend class JavaClass;
|
||||||
jclass activityClass;
|
|
||||||
jmethodID findClass;
|
|
||||||
jmethodID getDeclaredMethods;
|
jmethodID getDeclaredMethods;
|
||||||
jmethodID getFields;
|
jmethodID getFields;
|
||||||
jmethodID getParameterTypes;
|
jmethodID getParameterTypes;
|
||||||
@@ -229,7 +227,6 @@ class JavaClassWrapper : public Object {
|
|||||||
jmethodID Long_longValue;
|
jmethodID Long_longValue;
|
||||||
jmethodID Float_floatValue;
|
jmethodID Float_floatValue;
|
||||||
jmethodID Double_doubleValue;
|
jmethodID Double_doubleValue;
|
||||||
jobject classLoader;
|
|
||||||
|
|
||||||
bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig);
|
bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -239,6 +239,17 @@ public:
|
|||||||
JNISingleton() {
|
JNISingleton() {
|
||||||
#ifdef ANDROID_ENABLED
|
#ifdef ANDROID_ENABLED
|
||||||
instance = nullptr;
|
instance = nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~JNISingleton() {
|
||||||
|
#ifdef ANDROID_ENABLED
|
||||||
|
if (instance) {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(instance);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -321,6 +321,14 @@ void DirAccessJAndroid::setup(jobject p_dir_access_handler) {
|
|||||||
_current_is_hidden = env->GetMethodID(cls, "isCurrentHidden", "(II)Z");
|
_current_is_hidden = env->GetMethodID(cls, "isCurrentHidden", "(II)Z");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DirAccessJAndroid::terminate() {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(cls);
|
||||||
|
env->DeleteGlobalRef(dir_access_handler);
|
||||||
|
}
|
||||||
|
|
||||||
DirAccessJAndroid::DirAccessJAndroid() {
|
DirAccessJAndroid::DirAccessJAndroid() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ public:
|
|||||||
virtual uint64_t get_space_left() override;
|
virtual uint64_t get_space_left() override;
|
||||||
|
|
||||||
static void setup(jobject p_dir_access_handler);
|
static void setup(jobject p_dir_access_handler);
|
||||||
|
static void terminate();
|
||||||
|
|
||||||
DirAccessJAndroid();
|
DirAccessJAndroid();
|
||||||
~DirAccessJAndroid();
|
~DirAccessJAndroid();
|
||||||
|
|||||||
@@ -31,8 +31,12 @@
|
|||||||
#include "file_access_android.h"
|
#include "file_access_android.h"
|
||||||
|
|
||||||
#include "core/string/print_string.h"
|
#include "core/string/print_string.h"
|
||||||
|
#include "thread_jandroid.h"
|
||||||
|
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
|
||||||
AAssetManager *FileAccessAndroid::asset_manager = nullptr;
|
AAssetManager *FileAccessAndroid::asset_manager = nullptr;
|
||||||
|
jobject FileAccessAndroid::j_asset_manager = nullptr;
|
||||||
|
|
||||||
String FileAccessAndroid::get_path() const {
|
String FileAccessAndroid::get_path() const {
|
||||||
return path_src;
|
return path_src;
|
||||||
@@ -257,3 +261,16 @@ void FileAccessAndroid::close() {
|
|||||||
FileAccessAndroid::~FileAccessAndroid() {
|
FileAccessAndroid::~FileAccessAndroid() {
|
||||||
_close();
|
_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileAccessAndroid::setup(jobject p_asset_manager) {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
j_asset_manager = env->NewGlobalRef(p_asset_manager);
|
||||||
|
asset_manager = AAssetManager_fromJava(env, j_asset_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAccessAndroid::terminate() {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(j_asset_manager);
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,9 +35,13 @@
|
|||||||
|
|
||||||
#include <android/asset_manager.h>
|
#include <android/asset_manager.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
class FileAccessAndroid : public FileAccess {
|
class FileAccessAndroid : public FileAccess {
|
||||||
|
static AAssetManager *asset_manager;
|
||||||
|
static jobject j_asset_manager;
|
||||||
|
|
||||||
mutable AAsset *asset = nullptr;
|
mutable AAsset *asset = nullptr;
|
||||||
mutable uint64_t len = 0;
|
mutable uint64_t len = 0;
|
||||||
mutable uint64_t pos = 0;
|
mutable uint64_t pos = 0;
|
||||||
@@ -48,8 +52,6 @@ class FileAccessAndroid : public FileAccess {
|
|||||||
void _close();
|
void _close();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static AAssetManager *asset_manager;
|
|
||||||
|
|
||||||
virtual Error open_internal(const String &p_path, int p_mode_flags) override; // open a file
|
virtual Error open_internal(const String &p_path, int p_mode_flags) override; // open a file
|
||||||
virtual bool is_open() const override; // true when file is open
|
virtual bool is_open() const override; // true when file is open
|
||||||
|
|
||||||
@@ -92,6 +94,10 @@ public:
|
|||||||
|
|
||||||
virtual void close() override;
|
virtual void close() override;
|
||||||
|
|
||||||
|
static void setup(jobject p_asset_manager);
|
||||||
|
|
||||||
|
static void terminate();
|
||||||
|
|
||||||
~FileAccessAndroid();
|
~FileAccessAndroid();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -385,6 +385,14 @@ void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) {
|
|||||||
_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");
|
_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileAccessFilesystemJAndroid::terminate() {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(cls);
|
||||||
|
env->DeleteGlobalRef(file_access_handler);
|
||||||
|
}
|
||||||
|
|
||||||
void FileAccessFilesystemJAndroid::close() {
|
void FileAccessFilesystemJAndroid::close() {
|
||||||
if (is_open()) {
|
if (is_open()) {
|
||||||
_close();
|
_close();
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ public:
|
|||||||
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
|
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
|
||||||
|
|
||||||
static void setup(jobject p_file_access_handler);
|
static void setup(jobject p_file_access_handler);
|
||||||
|
static void terminate();
|
||||||
|
|
||||||
virtual uint64_t _get_modified_time(const String &p_file) override;
|
virtual uint64_t _get_modified_time(const String &p_file) override;
|
||||||
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
|
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
|
||||||
|
|||||||
@@ -1157,50 +1157,54 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
|
|||||||
JNIEnv *env = get_jni_env();
|
JNIEnv *env = get_jni_env();
|
||||||
ERR_FAIL_NULL(env);
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
jclass activity = env->FindClass("android/app/Activity");
|
|
||||||
jmethodID getClassLoader = env->GetMethodID(activity, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
|
||||||
classLoader = env->CallObjectMethod(p_activity, getClassLoader);
|
|
||||||
classLoader = (jclass)env->NewGlobalRef(classLoader);
|
|
||||||
jclass classLoaderClass = env->FindClass("java/lang/ClassLoader");
|
|
||||||
findClass = env->GetMethodID(classLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
|
||||||
|
|
||||||
jclass bclass = env->FindClass("java/lang/Class");
|
jclass bclass = env->FindClass("java/lang/Class");
|
||||||
getDeclaredMethods = env->GetMethodID(bclass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
|
getDeclaredMethods = env->GetMethodID(bclass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
|
||||||
getFields = env->GetMethodID(bclass, "getFields", "()[Ljava/lang/reflect/Field;");
|
getFields = env->GetMethodID(bclass, "getFields", "()[Ljava/lang/reflect/Field;");
|
||||||
Class_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
|
Class_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/reflect/Method");
|
bclass = env->FindClass("java/lang/reflect/Method");
|
||||||
getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
|
getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
|
||||||
getReturnType = env->GetMethodID(bclass, "getReturnType", "()Ljava/lang/Class;");
|
getReturnType = env->GetMethodID(bclass, "getReturnType", "()Ljava/lang/Class;");
|
||||||
getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
|
getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
|
||||||
getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
|
getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/reflect/Field");
|
bclass = env->FindClass("java/lang/reflect/Field");
|
||||||
Field_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
|
Field_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
|
||||||
Field_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
|
Field_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
|
||||||
Field_get = env->GetMethodID(bclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
Field_get = env->GetMethodID(bclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Boolean");
|
bclass = env->FindClass("java/lang/Boolean");
|
||||||
Boolean_booleanValue = env->GetMethodID(bclass, "booleanValue", "()Z");
|
Boolean_booleanValue = env->GetMethodID(bclass, "booleanValue", "()Z");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Byte");
|
bclass = env->FindClass("java/lang/Byte");
|
||||||
Byte_byteValue = env->GetMethodID(bclass, "byteValue", "()B");
|
Byte_byteValue = env->GetMethodID(bclass, "byteValue", "()B");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Character");
|
bclass = env->FindClass("java/lang/Character");
|
||||||
Character_characterValue = env->GetMethodID(bclass, "charValue", "()C");
|
Character_characterValue = env->GetMethodID(bclass, "charValue", "()C");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Short");
|
bclass = env->FindClass("java/lang/Short");
|
||||||
Short_shortValue = env->GetMethodID(bclass, "shortValue", "()S");
|
Short_shortValue = env->GetMethodID(bclass, "shortValue", "()S");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Integer");
|
bclass = env->FindClass("java/lang/Integer");
|
||||||
Integer_integerValue = env->GetMethodID(bclass, "intValue", "()I");
|
Integer_integerValue = env->GetMethodID(bclass, "intValue", "()I");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Long");
|
bclass = env->FindClass("java/lang/Long");
|
||||||
Long_longValue = env->GetMethodID(bclass, "longValue", "()J");
|
Long_longValue = env->GetMethodID(bclass, "longValue", "()J");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Float");
|
bclass = env->FindClass("java/lang/Float");
|
||||||
Float_floatValue = env->GetMethodID(bclass, "floatValue", "()F");
|
Float_floatValue = env->GetMethodID(bclass, "floatValue", "()F");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
|
|
||||||
bclass = env->FindClass("java/lang/Double");
|
bclass = env->FindClass("java/lang/Double");
|
||||||
Double_doubleValue = env->GetMethodID(bclass, "doubleValue", "()D");
|
Double_doubleValue = env->GetMethodID(bclass, "doubleValue", "()D");
|
||||||
|
env->DeleteLocalRef(bclass);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,11 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
|
|||||||
}
|
}
|
||||||
|
|
||||||
GodotIOJavaWrapper::~GodotIOJavaWrapper() {
|
GodotIOJavaWrapper::~GodotIOJavaWrapper() {
|
||||||
// nothing to do here for now
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(cls);
|
||||||
|
env->DeleteGlobalRef(godot_io_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject GodotIOJavaWrapper::get_instance() {
|
jobject GodotIOJavaWrapper::get_instance() {
|
||||||
@@ -82,7 +86,9 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
|
|||||||
JNIEnv *env = get_jni_env();
|
JNIEnv *env = get_jni_env();
|
||||||
ERR_FAIL_NULL_V(env, ERR_UNAVAILABLE);
|
ERR_FAIL_NULL_V(env, ERR_UNAVAILABLE);
|
||||||
jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());
|
jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());
|
||||||
return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;
|
Error result = env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;
|
||||||
|
env->DeleteLocalRef(jStr);
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return ERR_UNAVAILABLE;
|
return ERR_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
@@ -220,6 +226,7 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_type, int p_max
|
|||||||
ERR_FAIL_NULL(env);
|
ERR_FAIL_NULL(env);
|
||||||
jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
|
jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
|
||||||
env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_type, p_max_input_length, p_cursor_start, p_cursor_end);
|
env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_type, p_max_input_length, p_cursor_start, p_cursor_end);
|
||||||
|
env->DeleteLocalRef(jStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,13 @@ static void _terminate(JNIEnv *env, bool p_restart = false) {
|
|||||||
if (godot_io_java) {
|
if (godot_io_java) {
|
||||||
delete godot_io_java;
|
delete godot_io_java;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTS_Android::terminate();
|
||||||
|
FileAccessAndroid::terminate();
|
||||||
|
DirAccessJAndroid::terminate();
|
||||||
|
FileAccessFilesystemJAndroid::terminate();
|
||||||
|
NetSocketAndroid::terminate();
|
||||||
|
|
||||||
if (godot_java) {
|
if (godot_java) {
|
||||||
if (!restart_on_cleanup) {
|
if (!restart_on_cleanup) {
|
||||||
if (p_restart) {
|
if (p_restart) {
|
||||||
@@ -125,10 +132,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv
|
|||||||
|
|
||||||
init_thread_jandroid(jvm, env);
|
init_thread_jandroid(jvm, env);
|
||||||
|
|
||||||
jobject amgr = env->NewGlobalRef(p_asset_manager);
|
FileAccessAndroid::setup(p_asset_manager);
|
||||||
|
|
||||||
FileAccessAndroid::asset_manager = AAssetManager_fromJava(env, amgr);
|
|
||||||
|
|
||||||
DirAccessJAndroid::setup(p_directory_access_handler);
|
DirAccessJAndroid::setup(p_directory_access_handler);
|
||||||
FileAccessFilesystemJAndroid::setup(p_file_access_handler);
|
FileAccessFilesystemJAndroid::setup(p_file_access_handler);
|
||||||
NetSocketAndroid::setup(p_net_utils);
|
NetSocketAndroid::setup(p_net_utils);
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ void GodotJavaViewWrapper::configure_pointer_icon(int pointer_type, const String
|
|||||||
|
|
||||||
jstring jImagePath = env->NewStringUTF(image_path.utf8().get_data());
|
jstring jImagePath = env->NewStringUTF(image_path.utf8().get_data());
|
||||||
env->CallVoidMethod(_godot_view, _configure_pointer_icon, pointer_type, jImagePath, p_hotspot.x, p_hotspot.y);
|
env->CallVoidMethod(_godot_view, _configure_pointer_icon, pointer_type, jImagePath, p_hotspot.x, p_hotspot.y);
|
||||||
|
env->DeleteLocalRef(jImagePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,6 +172,8 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
|
|||||||
jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
|
jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
|
||||||
jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
|
jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
|
||||||
env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
|
env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
|
||||||
|
env->DeleteLocalRef(jStrMessage);
|
||||||
|
env->DeleteLocalRef(jStrTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +233,7 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) {
|
|||||||
ERR_FAIL_NULL(env);
|
ERR_FAIL_NULL(env);
|
||||||
jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
|
jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
|
||||||
env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
|
env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
|
||||||
|
env->DeleteLocalRef(jStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +256,9 @@ bool GodotJavaWrapper::request_permission(const String &p_name) {
|
|||||||
JNIEnv *env = get_jni_env();
|
JNIEnv *env = get_jni_env();
|
||||||
ERR_FAIL_NULL_V(env, false);
|
ERR_FAIL_NULL_V(env, false);
|
||||||
jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
|
jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
|
||||||
return env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
|
bool result = env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
|
||||||
|
env->DeleteLocalRef(jStrName);
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -340,7 +345,9 @@ int GodotJavaWrapper::create_new_godot_instance(const List<String> &args) {
|
|||||||
ERR_FAIL_NULL_V(env, 0);
|
ERR_FAIL_NULL_V(env, 0);
|
||||||
jobjectArray jargs = env->NewObjectArray(args.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
jobjectArray jargs = env->NewObjectArray(args.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
|
||||||
for (int i = 0; i < args.size(); i++) {
|
for (int i = 0; i < args.size(); i++) {
|
||||||
env->SetObjectArrayElement(jargs, i, env->NewStringUTF(args[i].utf8().get_data()));
|
jstring j_arg = env->NewStringUTF(args[i].utf8().get_data());
|
||||||
|
env->SetObjectArrayElement(jargs, i, j_arg);
|
||||||
|
env->DeleteLocalRef(j_arg);
|
||||||
}
|
}
|
||||||
return env->CallIntMethod(godot_instance, _create_new_godot_instance, jargs);
|
return env->CallIntMethod(godot_instance, _create_new_godot_instance, jargs);
|
||||||
} else {
|
} else {
|
||||||
@@ -355,6 +362,8 @@ void GodotJavaWrapper::begin_benchmark_measure(const String &p_context, const St
|
|||||||
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
|
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
|
||||||
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
|
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
|
||||||
env->CallVoidMethod(godot_instance, _begin_benchmark_measure, j_context, j_label);
|
env->CallVoidMethod(godot_instance, _begin_benchmark_measure, j_context, j_label);
|
||||||
|
env->DeleteLocalRef(j_context);
|
||||||
|
env->DeleteLocalRef(j_label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +374,8 @@ void GodotJavaWrapper::end_benchmark_measure(const String &p_context, const Stri
|
|||||||
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
|
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
|
||||||
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
|
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
|
||||||
env->CallVoidMethod(godot_instance, _end_benchmark_measure, j_context, j_label);
|
env->CallVoidMethod(godot_instance, _end_benchmark_measure, j_context, j_label);
|
||||||
|
env->DeleteLocalRef(j_context);
|
||||||
|
env->DeleteLocalRef(j_label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,6 +385,7 @@ void GodotJavaWrapper::dump_benchmark(const String &benchmark_file) {
|
|||||||
ERR_FAIL_NULL(env);
|
ERR_FAIL_NULL(env);
|
||||||
jstring j_benchmark_file = env->NewStringUTF(benchmark_file.utf8().get_data());
|
jstring j_benchmark_file = env->NewStringUTF(benchmark_file.utf8().get_data());
|
||||||
env->CallVoidMethod(godot_instance, _dump_benchmark, j_benchmark_file);
|
env->CallVoidMethod(godot_instance, _dump_benchmark, j_benchmark_file);
|
||||||
|
env->DeleteLocalRef(j_benchmark_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +395,9 @@ bool GodotJavaWrapper::has_feature(const String &p_feature) const {
|
|||||||
ERR_FAIL_NULL_V(env, false);
|
ERR_FAIL_NULL_V(env, false);
|
||||||
|
|
||||||
jstring j_feature = env->NewStringUTF(p_feature.utf8().get_data());
|
jstring j_feature = env->NewStringUTF(p_feature.utf8().get_data());
|
||||||
return env->CallBooleanMethod(godot_instance, _has_feature, j_feature);
|
bool result = env->CallBooleanMethod(godot_instance, _has_feature, j_feature);
|
||||||
|
env->DeleteLocalRef(j_feature);
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ void NetSocketAndroid::setup(jobject p_net_utils) {
|
|||||||
_multicast_lock_release = env->GetMethodID(cls, "multicastLockRelease", "()V");
|
_multicast_lock_release = env->GetMethodID(cls, "multicastLockRelease", "()V");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetSocketAndroid::terminate() {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(cls);
|
||||||
|
env->DeleteGlobalRef(net_utils);
|
||||||
|
}
|
||||||
|
|
||||||
void NetSocketAndroid::multicast_lock_acquire() {
|
void NetSocketAndroid::multicast_lock_acquire() {
|
||||||
if (_multicast_lock_acquire) {
|
if (_multicast_lock_acquire) {
|
||||||
JNIEnv *env = get_jni_env();
|
JNIEnv *env = get_jni_env();
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
static void make_default();
|
static void make_default();
|
||||||
static void setup(jobject p_net_utils);
|
static void setup(jobject p_net_utils);
|
||||||
|
static void terminate();
|
||||||
|
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
|
|||||||
@@ -736,6 +736,10 @@ void OS_Android::benchmark_dump() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OS_Android::_check_internal_feature_support(const String &p_feature) {
|
bool OS_Android::_check_internal_feature_support(const String &p_feature) {
|
||||||
|
if (p_feature == "macos" || p_feature == "web_ios" || p_feature == "web_macos" || p_feature == "windows") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_feature == "system_fonts") {
|
if (p_feature == "system_fonts") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,14 @@ void TTS_Android::setup(jobject p_tts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TTS_Android::terminate() {
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
ERR_FAIL_NULL(env);
|
||||||
|
|
||||||
|
env->DeleteGlobalRef(cls);
|
||||||
|
env->DeleteGlobalRef(tts);
|
||||||
|
}
|
||||||
|
|
||||||
void TTS_Android::_java_utterance_callback(int p_event, int p_id, int p_pos) {
|
void TTS_Android::_java_utterance_callback(int p_event, int p_id, int p_pos) {
|
||||||
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
|
ERR_FAIL_COND_MSG(!initialized, "Enable the \"audio/general/text_to_speech\" project setting to use text-to-speech.");
|
||||||
if (ids.has(p_id)) {
|
if (ids.has(p_id)) {
|
||||||
@@ -170,6 +178,8 @@ void TTS_Android::speak(const String &p_text, const String &p_voice, int p_volum
|
|||||||
jstring jStrT = env->NewStringUTF(p_text.utf8().get_data());
|
jstring jStrT = env->NewStringUTF(p_text.utf8().get_data());
|
||||||
jstring jStrV = env->NewStringUTF(p_voice.utf8().get_data());
|
jstring jStrV = env->NewStringUTF(p_voice.utf8().get_data());
|
||||||
env->CallVoidMethod(tts, _speak, jStrT, jStrV, CLAMP(p_volume, 0, 100), CLAMP(p_pitch, 0.f, 2.f), CLAMP(p_rate, 0.1f, 10.f), p_utterance_id, p_interrupt);
|
env->CallVoidMethod(tts, _speak, jStrT, jStrV, CLAMP(p_volume, 0, 100), CLAMP(p_pitch, 0.f, 2.f), CLAMP(p_rate, 0.1f, 10.f), p_utterance_id, p_interrupt);
|
||||||
|
env->DeleteLocalRef(jStrT);
|
||||||
|
env->DeleteLocalRef(jStrV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class TTS_Android {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static void setup(jobject p_tts);
|
static void setup(jobject p_tts);
|
||||||
|
static void terminate();
|
||||||
static void _java_utterance_callback(int p_event, int p_id, int p_pos);
|
static void _java_utterance_callback(int p_event, int p_id, int p_pos);
|
||||||
|
|
||||||
static bool is_speaking();
|
static bool is_speaking();
|
||||||
|
|||||||
Reference in New Issue
Block a user