CAndroidVMHelper.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * CAndroidVMHelper.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "CAndroidVMHelper.h"
  11. static JavaVM * vmCache = nullptr;
  12. /// cached java classloader so that we can find our classes from other threads
  13. static jobject vcmiClassLoader;
  14. static jmethodID vcmiFindClassMethod;
  15. void CAndroidVMHelper::cacheVM(JNIEnv * env)
  16. {
  17. env->GetJavaVM(&vmCache);
  18. }
  19. void CAndroidVMHelper::cacheVM(JavaVM * vm)
  20. {
  21. vmCache = vm;
  22. }
  23. CAndroidVMHelper::CAndroidVMHelper()
  24. {
  25. auto res = vmCache->GetEnv((void **) &envPtr, JNI_VERSION_1_1);
  26. if(res == JNI_EDETACHED)
  27. {
  28. auto attachRes = vmCache->AttachCurrentThread(&envPtr, nullptr);
  29. if(attachRes == JNI_OK)
  30. {
  31. detachInDestructor = true; // only detach if we actually attached env
  32. }
  33. }
  34. else
  35. {
  36. detachInDestructor = false;
  37. }
  38. }
  39. CAndroidVMHelper::~CAndroidVMHelper()
  40. {
  41. if(envPtr && detachInDestructor)
  42. {
  43. vmCache->DetachCurrentThread();
  44. envPtr = nullptr;
  45. }
  46. }
  47. JNIEnv * CAndroidVMHelper::get()
  48. {
  49. return envPtr;
  50. }
  51. jclass CAndroidVMHelper::findClassloadedClass(const std::string & name)
  52. {
  53. auto env = get();
  54. return static_cast<jclass>(env->CallObjectMethod(vcmiClassLoader, vcmiFindClassMethod,
  55. env->NewStringUTF(name.c_str())));;
  56. }
  57. void CAndroidVMHelper::callStaticVoidMethod(const std::string & cls, const std::string & method,
  58. bool classloaded /*=false*/)
  59. {
  60. auto env = get();
  61. auto javaHelper = findClass(cls, classloaded);
  62. auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), "()V");
  63. env->CallStaticVoidMethod(javaHelper, methodId);
  64. }
  65. std::string CAndroidVMHelper::callStaticStringMethod(const std::string & cls, const std::string & method,
  66. bool classloaded /*=false*/)
  67. {
  68. auto env = get();
  69. auto javaHelper = findClass(cls, classloaded);
  70. auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), "()Ljava/lang/String;");
  71. jstring jres = static_cast<jstring>(env->CallStaticObjectMethod(javaHelper, methodId));
  72. return std::string(env->GetStringUTFChars(jres, nullptr));
  73. }
  74. jclass CAndroidVMHelper::findClass(const std::string & name, bool classloaded)
  75. {
  76. if(classloaded)
  77. {
  78. return findClassloadedClass(name);
  79. }
  80. return get()->FindClass(name.c_str());
  81. }
  82. extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_initClassloader(JNIEnv * baseEnv, jobject * cls)
  83. {
  84. CAndroidVMHelper::cacheVM(baseEnv);
  85. CAndroidVMHelper envHelper;
  86. auto env = envHelper.get();
  87. auto anyVCMIClass = env->FindClass(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS);
  88. jclass classClass = env->GetObjectClass(anyVCMIClass);
  89. auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
  90. auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
  91. vcmiClassLoader = (jclass) env->NewGlobalRef(env->CallObjectMethod(anyVCMIClass, getClassLoaderMethod));
  92. vcmiFindClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  93. }