diff --git a/src/android/app/src/main/jni/applets/mii_selector.cpp b/src/android/app/src/main/jni/applets/mii_selector.cpp index 95490c7a2..0e8e79238 100644 --- a/src/android/app/src/main/jni/applets/mii_selector.cpp +++ b/src/android/app/src/main/jni/applets/mii_selector.cpp @@ -34,8 +34,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) { // List mii names // The 'Standard Mii' is not included here as we need Java side to translate it - const jclass string_class = - reinterpret_cast(env->NewGlobalRef(env->FindClass("java/lang/String"))); + const jclass string_class = reinterpret_cast(env->FindClass("java/lang/String")); const jobjectArray array = env->NewObjectArray(static_cast(miis.size()), string_class, nullptr); for (std::size_t i = 0; i < miis.size(); ++i) { @@ -45,7 +44,6 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) { env->SetObjectField( java_config, env->GetFieldID(s_mii_selector_config_class, "mii_names", "[Ljava/lang/String;"), array); - env->DeleteGlobalRef(string_class); // Invoke backend Execute method jobject data = diff --git a/src/android/app/src/main/jni/applets/swkbd.cpp b/src/android/app/src/main/jni/applets/swkbd.cpp index 27d5a28c0..4b339aa29 100644 --- a/src/android/app/src/main/jni/applets/swkbd.cpp +++ b/src/android/app/src/main/jni/applets/swkbd.cpp @@ -41,8 +41,7 @@ static jobject ToJavaKeyboardConfig(const Frontend::KeyboardConfig& config) { env->GetFieldID(s_keyboard_config_class, "hint_text", "Ljava/lang/String;"), env->NewStringUTF(config.hint_text.c_str())); if (config.has_custom_button_text) { - const jclass string_class = - reinterpret_cast(env->NewGlobalRef(env->FindClass("java/lang/String"))); + const jclass string_class = reinterpret_cast(env->FindClass("java/lang/String")); const jobjectArray array = env->NewObjectArray(static_cast(config.button_text.size()), string_class, env->NewStringUTF(config.button_text[0].c_str())); @@ -53,7 +52,6 @@ static jobject ToJavaKeyboardConfig(const Frontend::KeyboardConfig& config) { env->SetObjectField( object, env->GetFieldID(s_keyboard_config_class, "button_text", "[Ljava/lang/String;"), array); - env->DeleteGlobalRef(string_class); } return object; } diff --git a/src/android/app/src/main/jni/camera/still_image_camera.cpp b/src/android/app/src/main/jni/camera/still_image_camera.cpp index 992b65ba7..496b51fa8 100644 --- a/src/android/app/src/main/jni/camera/still_image_camera.cpp +++ b/src/android/app/src/main/jni/camera/still_image_camera.cpp @@ -7,7 +7,6 @@ #include "common/logging/log.h" #include "core/frontend/camera/blank_camera.h" #include "jni/camera/still_image_camera.h" -#include "jni/id_cache.h" static jclass s_still_image_camera_helper_class; static jmethodID s_open_file_picker; @@ -29,7 +28,8 @@ void CleanupJNI(JNIEnv* env) { env->DeleteGlobalRef(s_still_image_camera_helper_class); } -Interface::Interface(jstring path_, const Service::CAM::Flip& flip) : path(path_) { +Interface::Interface(SharedGlobalRef path_, const Service::CAM::Flip& flip) + : path(std::move(path_)) { mirror = base_mirror = flip == Service::CAM::Flip::Horizontal || flip == Service::CAM::Flip::Reverse; invert = base_invert = @@ -37,14 +37,14 @@ Interface::Interface(jstring path_, const Service::CAM::Flip& flip) : path(path_ } Interface::~Interface() { - Factory::last_path = nullptr; + Factory::last_path.reset(); } void Interface::StartCapture() { JNIEnv* env = IDCache::GetEnvForThread(); jobject bitmap = - env->CallStaticObjectMethod(s_still_image_camera_helper_class, s_load_image_from_file, path, - resolution.width, resolution.height); + env->CallStaticObjectMethod(s_still_image_camera_helper_class, s_load_image_from_file, + path.get(), resolution.width, resolution.height); if (bitmap == nullptr) { LOG_ERROR(Frontend, "Could not load image from file"); opened = false; @@ -118,7 +118,7 @@ bool Interface::IsPreviewAvailable() { return opened; } -jstring Factory::last_path{}; +SharedGlobalRef Factory::last_path{}; std::unique_ptr Factory::Create(const std::string& config, const Service::CAM::Flip& flip) { @@ -134,8 +134,9 @@ std::unique_ptr Factory::Create(const std::string& config, if (path == nullptr) { return std::make_unique(); } else { - last_path = path; - return std::make_unique(path, flip); + auto shared_path = NewSharedGlobalRef(path); + last_path = shared_path; + return std::make_unique(std::move(shared_path), flip); } } diff --git a/src/android/app/src/main/jni/camera/still_image_camera.h b/src/android/app/src/main/jni/camera/still_image_camera.h index 01a201096..2ac81dacf 100644 --- a/src/android/app/src/main/jni/camera/still_image_camera.h +++ b/src/android/app/src/main/jni/camera/still_image_camera.h @@ -11,12 +11,13 @@ #include "common/common_types.h" #include "core/frontend/camera/factory.h" #include "core/frontend/camera/interface.h" +#include "jni/id_cache.h" namespace Camera::StillImage { class Interface final : public CameraInterface { public: - Interface(jstring path, const Service::CAM::Flip& flip); + Interface(SharedGlobalRef path, const Service::CAM::Flip& flip); ~Interface(); void StartCapture() override; void StopCapture() override{}; @@ -29,7 +30,7 @@ public: bool IsPreviewAvailable() override; private: - jstring path; + SharedGlobalRef path; Service::CAM::Resolution resolution; // Flipping parameters. mirror = horizontal, invert = vertical. @@ -50,7 +51,7 @@ public: private: /// Record the path chosen to avoid multiple prompt problem - static jstring last_path; + static SharedGlobalRef last_path; friend class Interface; }; diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h index 86a9a5703..f210e848c 100644 --- a/src/android/app/src/main/jni/id_cache.h +++ b/src/android/app/src/main/jni/id_cache.h @@ -4,6 +4,8 @@ #pragma once +#include +#include #include namespace IDCache { @@ -19,3 +21,20 @@ jmethodID GetExitEmulationActivity(); jmethodID GetRequestCameraPermission(); } // namespace IDCache + +template +using SharedGlobalRef = std::shared_ptr>; + +struct SharedGlobalRefDeleter { + void operator()(jobject ptr) { + JNIEnv* env = IDCache::GetEnvForThread(); + env->DeleteGlobalRef(ptr); + } +}; + +template +SharedGlobalRef NewSharedGlobalRef(T object) { + JNIEnv* env = IDCache::GetEnvForThread(); + auto* global_ref = reinterpret_cast(env->NewGlobalRef(object)); + return SharedGlobalRef(global_ref, SharedGlobalRefDeleter()); +}