2
0

CAndroidVMHelper.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. #ifdef VCMI_ANDROID
  12. VCMI_LIB_NAMESPACE_BEGIN
  13. static JavaVM * vmCache = nullptr;
  14. /// cached java classloader so that we can find our classes from other threads
  15. static jobject vcmiClassLoader;
  16. static jmethodID vcmiFindClassMethod;
  17. bool CAndroidVMHelper::alwaysUseLoadedClass = false;
  18. void CAndroidVMHelper::cacheVM(JNIEnv * env)
  19. {
  20. env->GetJavaVM(&vmCache);
  21. }
  22. CAndroidVMHelper::CAndroidVMHelper()
  23. {
  24. auto res = vmCache->GetEnv((void **) &envPtr, JNI_VERSION_1_1);
  25. if(res == JNI_EDETACHED)
  26. {
  27. auto attachRes = vmCache->AttachCurrentThread(&envPtr, nullptr);
  28. if(attachRes == JNI_OK)
  29. {
  30. detachInDestructor = true; // only detach if we actually attached env
  31. }
  32. }
  33. else
  34. {
  35. detachInDestructor = false;
  36. }
  37. }
  38. CAndroidVMHelper::~CAndroidVMHelper()
  39. {
  40. if(envPtr && detachInDestructor)
  41. {
  42. vmCache->DetachCurrentThread();
  43. envPtr = nullptr;
  44. }
  45. }
  46. JNIEnv * CAndroidVMHelper::get()
  47. {
  48. return envPtr;
  49. }
  50. jclass CAndroidVMHelper::findClassloadedClass(const std::string & name)
  51. {
  52. auto env = get();
  53. return static_cast<jclass>(env->CallObjectMethod(vcmiClassLoader, vcmiFindClassMethod,
  54. env->NewStringUTF(name.c_str())));
  55. }
  56. void CAndroidVMHelper::callStaticVoidMethod(const std::string & cls, const std::string & method,
  57. bool classloaded)
  58. {
  59. auto env = get();
  60. auto javaHelper = findClass(cls, classloaded);
  61. auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), "()V");
  62. env->CallStaticVoidMethod(javaHelper, methodId);
  63. }
  64. std::string CAndroidVMHelper::callStaticStringMethod(const std::string & cls, const std::string & method,
  65. bool classloaded)
  66. {
  67. auto env = get();
  68. auto javaHelper = findClass(cls, classloaded);
  69. auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), "()Ljava/lang/String;");
  70. jstring jres = static_cast<jstring>(env->CallStaticObjectMethod(javaHelper, methodId));
  71. return std::string(env->GetStringUTFChars(jres, nullptr));
  72. }
  73. void CAndroidVMHelper::callCustomMethod(const std::string & cls, const std::string & method,
  74. const std::string & signature,
  75. std::function<void(JNIEnv *, jclass, jmethodID)> fun, bool classloaded)
  76. {
  77. auto env = get();
  78. auto javaHelper = findClass(cls, classloaded);
  79. auto methodId = env->GetStaticMethodID(javaHelper, method.c_str(), signature.c_str());
  80. fun(env, javaHelper, methodId);
  81. }
  82. jclass CAndroidVMHelper::findClass(const std::string & name, bool classloaded)
  83. {
  84. if(alwaysUseLoadedClass || classloaded)
  85. {
  86. return findClassloadedClass(name);
  87. }
  88. return get()->FindClass(name.c_str());
  89. }
  90. void CAndroidVMHelper::initClassloader(void * baseEnv)
  91. {
  92. CAndroidVMHelper::cacheVM(static_cast<JNIEnv *>(baseEnv));
  93. CAndroidVMHelper envHelper;
  94. auto env = envHelper.get();
  95. auto anyVCMIClass = env->FindClass(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS);
  96. jclass classClass = env->GetObjectClass(anyVCMIClass);
  97. auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
  98. auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
  99. vcmiClassLoader = (jclass) env->NewGlobalRef(env->CallObjectMethod(anyVCMIClass, getClassLoaderMethod));
  100. vcmiFindClassMethod = env->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
  101. }
  102. VCMI_LIB_NAMESPACE_END
  103. #endif