1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00
vcmi/lib/CAndroidVMHelper.cpp
Fay b5daa24982 Android support (#299)
* AI libs registering shenanigans on android;
* Fixed resolution aspect + mouse event scaling;
* Proper server init/deinit (through android IPC);
Enabled threaded init in CMT;
* Prevented a deadlock in logger on some devices;
* Fixed frozen intro frame after interrupting the video;
Added android progressbar displaying during initial data loading;
* Hacky fix for choppy animations during heroes movement (should look better now, but it's definitely not a good solution);
* Changes/fixes for new android launcher building process;
* Fixed app hang after getting SDL_QUIT when activity was destroyed;
* Functioanal, configurable advmap swiping support;
* VCMI changes cleanup;
Added few missing VCMI_ANDROID guards on swipe mechanics;
* Removed unneeded sleep in server startup code for android;
* Removed android ioapi hack (fixed in newest ndk);
* Removed unused android's library loading logic;
* Added android's swipe option to settings schema;
* Moved NO_STD_TOSTRING to be defined in global.h instead of build files;
2017-05-25 20:57:20 +03:00

106 lines
3.0 KiB
C++

/*
* CAndroidVMHelper.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "CAndroidVMHelper.h"
static JavaVM * vmCache = nullptr;
/// cached java classloader so that we can find our classes from other threads
static jobject vcmiClassLoader;
static jmethodID vcmiFindClassMethod;
void CAndroidVMHelper::cacheVM(JNIEnv * env)
{
env->GetJavaVM(&vmCache);
}
void CAndroidVMHelper::cacheVM(JavaVM * vm)
{
vmCache = vm;
}
CAndroidVMHelper::CAndroidVMHelper()
{
auto res = vmCache->GetEnv((void **) &envPtr, JNI_VERSION_1_1);
if(res == JNI_EDETACHED)
{
auto attachRes = vmCache->AttachCurrentThread(&envPtr, nullptr);
if(attachRes == JNI_OK)
{
detachInDestructor = true; // only detach if we actually attached env
}
}
else
{
detachInDestructor = false;
}
}
CAndroidVMHelper::~CAndroidVMHelper()
{
if(envPtr && detachInDestructor)
{
vmCache->DetachCurrentThread();
envPtr = nullptr;
}
}
JNIEnv * CAndroidVMHelper::get()
{
return envPtr;
}
jclass CAndroidVMHelper::findClassloadedClass(const std::string & name)
{
auto env = get();
return static_cast<jclass>(env->CallObjectMethod(vcmiClassLoader, vcmiFindClassMethod,
env->NewStringUTF(name.c_str())));;
}
void CAndroidVMHelper::callStaticVoidMethod(const std::string & cls, const std::string & method,
bool classloaded /*=false*/)
{
auto env = get();
auto javaHelper = findClass(cls, classloaded);
auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), "()V");
env->CallStaticVoidMethod(javaHelper, methodId);
}
std::string CAndroidVMHelper::callStaticStringMethod(const std::string & cls, const std::string & method,
bool classloaded /*=false*/)
{
auto env = get();
auto javaHelper = findClass(cls, classloaded);
auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), "()Ljava/lang/String;");
jstring jres = static_cast<jstring>(env->CallStaticObjectMethod(javaHelper, methodId));
return std::string(env->GetStringUTFChars(jres, nullptr));
}
jclass CAndroidVMHelper::findClass(const std::string & name, bool classloaded)
{
if(classloaded)
{
return findClassloadedClass(name);
}
return get()->FindClass(name.c_str());
}
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_initClassloader(JNIEnv * baseEnv, jobject * cls)
{
CAndroidVMHelper::cacheVM(baseEnv);
CAndroidVMHelper envHelper;
auto env = envHelper.get();
auto anyVCMIClass = env->FindClass(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS);
jclass classClass = env->GetObjectClass(anyVCMIClass);
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
vcmiClassLoader = (jclass) env->NewGlobalRef(env->CallObjectMethod(anyVCMIClass, getClassLoaderMethod));
vcmiFindClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
}