1
0
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:
Gymnasiast
2022-01-11 11:57:54 +01:00
parent b826c0706a
commit 0aa256a26a
7 changed files with 80 additions and 94 deletions

View File

@@ -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