mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-21 05:53:02 +01:00
Move remaining stuff in Android.cpp
This commit is contained in:
@@ -13,6 +13,20 @@
|
||||
# include "../localisation/Language.h"
|
||||
# include "Platform2.h"
|
||||
|
||||
# include <SDL.h>
|
||||
# include <jni.h>
|
||||
|
||||
AndroidClassLoader::~AndroidClassLoader()
|
||||
{
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
env->DeleteGlobalRef(_classLoader);
|
||||
}
|
||||
|
||||
jobject AndroidClassLoader::_classLoader;
|
||||
jmethodID AndroidClassLoader::_findClassMethod;
|
||||
|
||||
static std::shared_ptr<AndroidClassLoader> acl;
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
std::string GetFolderPath(SPECIAL_FOLDER folder)
|
||||
@@ -99,6 +113,53 @@ namespace Platform
|
||||
|
||||
return displayScale;
|
||||
}
|
||||
|
||||
void AndroidInitClassLoader()
|
||||
{
|
||||
acl = std::make_shared<AndroidClassLoader>();
|
||||
}
|
||||
|
||||
jclass AndroidFindClass(JNIEnv* env, std::string_view name)
|
||||
{
|
||||
return static_cast<jclass>(env->CallObjectMethod(
|
||||
AndroidClassLoader::_classLoader, AndroidClassLoader::_findClassMethod,
|
||||
env->NewStringUTF(std::string(name).c_str())));
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
AndroidClassLoader::AndroidClassLoader()
|
||||
{
|
||||
log_info("Obtaining JNI class loader");
|
||||
|
||||
// This is a workaround to be able to call JNI's ClassLoader from non-main
|
||||
// thread, based on https://stackoverflow.com/a/16302771
|
||||
|
||||
// Apparently it's OK to use it from across different thread, but JNI
|
||||
// only looks for ClassLoader in the _current_ thread and fails to find
|
||||
// it when searched for from a native library's non-main thread.
|
||||
|
||||
// The solution below works by obtaining a ClassLoader reference in main
|
||||
// thread and caching it for future use from any thread, instead of using
|
||||
// it via env->FindClass(). ClassLoader itself is abstract, so we cannot
|
||||
// create it directly; instead we take an arbitrary class and call
|
||||
// getClassLoader() on it to create a reference that way.
|
||||
|
||||
// If we're here, SDL's JNI_OnLoad has already been called and set env
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
|
||||
// Take an arbitrary class. While the class does not really matter, it
|
||||
// makes sense to use one that's most likely already loaded and is unlikely
|
||||
// to be removed from code.
|
||||
auto randomClass = env->FindClass("io/openrct2/MainActivity");
|
||||
jclass classClass = env->GetObjectClass(randomClass);
|
||||
|
||||
// Get its class loader
|
||||
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
|
||||
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
|
||||
// Store the class loader and its findClass method for future use
|
||||
_classLoader = env->NewGlobalRef(env->CallObjectMethod(randomClass, getClassLoaderMethod));
|
||||
_findClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user