mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-16 03:23:15 +01:00
Move remaining stuff in Android.cpp
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
# include "../platform/Platform2.h"
|
||||
# include "../platform/platform.h"
|
||||
# include "IStream.hpp"
|
||||
# include "MemoryStream.h"
|
||||
@@ -30,7 +31,7 @@ public:
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
|
||||
jclass jniClass = platform_android_find_class(env, "io/openrct2/ZipArchive");
|
||||
jclass jniClass = Platform::AndroidFindClass(env, "io/openrct2/ZipArchive");
|
||||
jmethodID constructor = env->GetMethodID(jniClass, "<init>", "(Ljava/lang/String;)V");
|
||||
|
||||
jstring jniPath = env->NewStringUTF(path.data());
|
||||
|
||||
@@ -783,7 +783,6 @@
|
||||
<ClCompile Include="peep\PeepData.cpp" />
|
||||
<ClCompile Include="peep\RideUseSystem.cpp" />
|
||||
<ClCompile Include="PlatformEnvironment.cpp" />
|
||||
<ClCompile Include="platform\Android.cpp" />
|
||||
<ClCompile Include="platform\Crash.cpp" />
|
||||
<ClCompile Include="platform\Platform.Android.cpp" />
|
||||
<ClCompile Include="platform\Platform.Linux.cpp" />
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
# include "../config/Config.h"
|
||||
# include "../localisation/Language.h"
|
||||
# include "../util/Util.h"
|
||||
# include "platform.h"
|
||||
|
||||
# include <SDL.h>
|
||||
# include <jni.h>
|
||||
# include <wchar.h>
|
||||
|
||||
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;");
|
||||
}
|
||||
|
||||
AndroidClassLoader::~AndroidClassLoader()
|
||||
{
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
env->DeleteGlobalRef(_classLoader);
|
||||
}
|
||||
|
||||
jobject AndroidClassLoader::_classLoader;
|
||||
jmethodID AndroidClassLoader::_findClassMethod;
|
||||
|
||||
static std::shared_ptr<AndroidClassLoader> acl;
|
||||
|
||||
void platform_android_init_class_loader()
|
||||
{
|
||||
acl = std::make_shared<AndroidClassLoader>();
|
||||
}
|
||||
|
||||
jclass platform_android_find_class(JNIEnv* env, const char* name)
|
||||
{
|
||||
return static_cast<jclass>(
|
||||
env->CallObjectMethod(AndroidClassLoader::_classLoader, AndroidClassLoader::_findClassMethod, env->NewStringUTF(name)));
|
||||
}
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -80,6 +80,10 @@ namespace Platform
|
||||
const uint32_t iconIndex);
|
||||
void RemoveFileAssociations();
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
void AndroidInitClassLoader();
|
||||
jclass AndroidFindClass(JNIEnv* env, std::string_view name);
|
||||
#endif
|
||||
|
||||
bool IsRunningInWine();
|
||||
bool IsColourTerminalSupported();
|
||||
@@ -87,3 +91,15 @@ namespace Platform
|
||||
utf8* StrDecompToPrecomp(utf8* input);
|
||||
bool RequireNewWindow(bool openGL);
|
||||
} // namespace Platform
|
||||
|
||||
#ifdef __ANDROID__
|
||||
class AndroidClassLoader
|
||||
{
|
||||
public:
|
||||
AndroidClassLoader();
|
||||
~AndroidClassLoader();
|
||||
static jobject _classLoader;
|
||||
static jmethodID _findClassMethod;
|
||||
};
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
||||
@@ -223,7 +223,7 @@ void core_init()
|
||||
initialised = true;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
platform_android_init_class_loader();
|
||||
Platform::AndroidInitClassLoader();
|
||||
#endif // __ANDROID__
|
||||
|
||||
platform_ticks_init();
|
||||
|
||||
@@ -124,17 +124,3 @@ bool platform_setup_uri_protocol();
|
||||
// as it requires external linkage, which 'static' prevents
|
||||
__declspec(dllexport) int32_t StartOpenRCT2(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int32_t nCmdShow);
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef __ANDROID__
|
||||
class AndroidClassLoader
|
||||
{
|
||||
public:
|
||||
AndroidClassLoader();
|
||||
~AndroidClassLoader();
|
||||
static jobject _classLoader;
|
||||
static jmethodID _findClassMethod;
|
||||
};
|
||||
|
||||
void platform_android_init_class_loader();
|
||||
jclass platform_android_find_class(JNIEnv* env, const char* name);
|
||||
#endif // __ANDROID__
|
||||
|
||||
Reference in New Issue
Block a user