diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index fcfd3d8..6a43771 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -970,7 +970,6 @@ pub unsafe extern "C" fn _rust_glue_entry(native_app: *mut ffi::android_app) { let (jvm, jni_activity) = unsafe { let jvm = (*(*native_app).activity).vm; let activity: jobject = (*(*native_app).activity).javaGameActivity; - ndk_context::initialize_android_context(jvm.cast(), activity.cast()); (jni::JavaVM::from_raw(jvm), activity) }; // Note: At this point we can assume jni::JavaVM::singleton is initialized @@ -1011,8 +1010,6 @@ pub unsafe extern "C" fn _rust_glue_entry(native_app: *mut ffi::android_app) { // "Note that this method can be called from any thread; it will send a message // to the main thread of the process where the Java finish call will take place" ffi::GameActivity_finish((*native_app).activity); - - ndk_context::release_android_context(); } Ok(()) diff --git a/android-activity/src/native_activity/glue.rs b/android-activity/src/native_activity/glue.rs index 12d37cb..e5cd8c5 100644 --- a/android-activity/src/native_activity/glue.rs +++ b/android-activity/src/native_activity/glue.rs @@ -875,7 +875,6 @@ fn rust_glue_entry(rust_glue: NativeActivityGlue, activity: *mut ndk_sys::ANativ let (jvm, jni_activity) = unsafe { let jvm: *mut jni::sys::JavaVM = (*activity).vm.cast(); let jni_activity: jni::sys::jobject = (*activity).clazz as _; // Completely bogus name; this is the _instance_ not class pointer - ndk_context::initialize_android_context(jvm.cast(), jni_activity.cast()); (jni::JavaVM::from_raw(jvm), jni_activity) }; // Note: At this point we can assume jni::JavaVM::singleton is initialized @@ -923,8 +922,6 @@ fn rust_glue_entry(rust_glue: NativeActivityGlue, activity: *mut ndk_sys::ANativ // "Note that this method can be called from any thread; it will send a message // to the main thread of the process where the Java finish call will take place" ndk_sys::ANativeActivity_finish(activity); - - ndk_context::release_android_context(); } rust_glue.notify_main_thread_stopped_running(); diff --git a/android-activity/src/util.rs b/android-activity/src/util.rs index 0c3b5da..22ed657 100644 --- a/android-activity/src/util.rs +++ b/android-activity/src/util.rs @@ -1,5 +1,5 @@ use jni::{ - jni_str, + jni_sig, jni_str, objects::{JObject, JString, JThread}, vm::JavaVM, }; @@ -12,6 +12,7 @@ use std::{ fd::{FromRawFd as _, RawFd}, raw::c_char, }, + sync::OnceLock, }; pub fn try_get_path_from_ptr(path: *const c_char) -> Option { @@ -117,6 +118,24 @@ pub(crate) fn abort_on_panic(f: impl FnOnce() -> R) -> R { }) } +static NDK_CONTEXT_ONCE: OnceLock<()> = OnceLock::new(); + +// Get the Application instance from the Activity +fn get_application<'local, 'any>( + env: &mut jni::Env<'local>, + activity: &JObject<'any>, +) -> jni::errors::Result> { + let app = env + .call_method( + activity, + jni_str!("getApplication"), + jni_sig!(() -> android.app.Application), + &[], + )? + .l()?; + Ok(app) +} + /// Name the Java Thread + native thread "android_main" and set the Java Thread context class loader /// so that jni code can more-easily find non-system Java classes. pub(crate) fn init_android_main_thread( @@ -125,6 +144,18 @@ pub(crate) fn init_android_main_thread( ) -> jni::errors::Result<()> { vm.with_local_frame(10, |env| -> jni::errors::Result<()> { let activity_class = env.get_object_class(jni_activity)?; + + if let Ok(application) = get_application(env, jni_activity) { + NDK_CONTEXT_ONCE.get_or_init(|| unsafe { + let app_global = env + .new_global_ref(application) + .expect("Failed to create global ref for Application"); + // Make sure we don't delete the global reference via Drop + let app_global = app_global.into_raw(); + ndk_context::initialize_android_context(vm.get_raw().cast(), app_global.cast()); + }); + } + let class_loader = activity_class.get_class_loader(env)?; let thread = JThread::current_thread(env)?;