diff --git a/android/sdk/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp b/android/sdk/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp index 2c628ba25..62d5b8b05 100644 --- a/android/sdk/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp +++ b/android/sdk/src/main/cpp/app/organicmaps/sdk/OrganicMaps.cpp @@ -29,7 +29,7 @@ JNIEXPORT void JNICALL Java_app_organicmaps_sdk_OrganicMaps_nativeInitFramework( { if (!g_framework) { - g_framework = std::make_unique([onComplete = jni::make_global_ref(onComplete)]() + g_framework = std::make_unique([onComplete = jni::make_global_ref_safe(onComplete)]() { JNIEnv * env = jni::GetEnv(); jmethodID const methodId = jni::GetMethodID(env, *onComplete, "run", "()V"); diff --git a/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.cpp b/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.cpp index 62ef0ddc4..9d3e3990a 100644 --- a/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.cpp +++ b/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.cpp @@ -98,18 +98,26 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *) namespace jni { -JNIEnv * GetEnv() +JNIEnv * GetEnvSafe() { JNIEnv * env; auto const res = g_jvm->GetEnv((void **)&env, JNI_VERSION_1_6); if (res != JNI_OK) { LOG(LERROR, ("Can't get JNIEnv. Is the thread attached to JVM?", res)); - MYTHROW(RootException, ("Can't get JNIEnv. Is the thread attached to JVM?", res)); + env = nullptr; } return env; } +JNIEnv * GetEnv() +{ + JNIEnv * env = GetEnvSafe(); + if (env == nullptr) + MYTHROW(RootException, ("Can't get JNIEnv. Is the thread attached to JVM?")); + return env; +} + JavaVM * GetJVM() { ASSERT(g_jvm, ("JVM is not initialized")); @@ -218,6 +226,20 @@ std::shared_ptr make_global_ref(jobject obj) }); } +// https://github.com/organicmaps/organicmaps/issues/9397 +/// @todo There are no other ideas, let's try a safe version with a forever global ref .. +std::shared_ptr make_global_ref_safe(jobject obj) +{ + jobject * ref = new jobject(GetEnv()->NewGlobalRef(obj)); + return std::shared_ptr(ref, [](jobject * ref) + { + JNIEnv * env = GetEnvSafe(); + if (env) + env->DeleteGlobalRef(*ref); + delete ref; + }); +} + std::string ToNativeString(JNIEnv * env, jthrowable const & e) { jni::TScopedLocalClassRef logClassRef(env, env->FindClass("android/util/Log")); diff --git a/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.hpp b/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.hpp index 4da33cbd5..2775d9f9a 100644 --- a/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.hpp +++ b/android/sdk/src/main/cpp/app/organicmaps/sdk/core/jni_helper.hpp @@ -66,6 +66,8 @@ bool HandleJavaException(JNIEnv * env); base::LogLevel GetLogLevelForException(JNIEnv * env, jthrowable const & e); std::shared_ptr make_global_ref(jobject obj); +std::shared_ptr make_global_ref_safe(jobject obj); + using TScopedLocalRef = ScopedLocalRef; using TScopedLocalClassRef = ScopedLocalRef; using TScopedLocalObjectArrayRef = ScopedLocalRef;