Use an obtained class loader instead of the default

This commit is contained in:
folecr 2013-07-19 15:01:42 -07:00
parent 669427363f
commit 53b1a92773
3 changed files with 104 additions and 66 deletions

View File

@ -29,70 +29,77 @@ THE SOFTWARE.
#define LOG_TAG "JniHelper"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
extern "C"
{
static JNIEnv* _getJNIEnv(void) {
static JNIEnv* _getJNIEnv(void) {
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
return NULL;
}
JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
return NULL;
}
JNIEnv *env = NULL;
// get jni environment
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
JNIEnv *env = NULL;
// get jni environment
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
switch (ret) {
case JNI_OK :
// Success!
return env;
switch (ret) {
case JNI_OK :
// Success!
case JNI_EDETACHED :
// Thread not attached
// TODO : If calling AttachCurrentThread() on a native thread
// must call DetachCurrentThread() in future.
// see: http://developer.android.com/guide/practices/design/jni.html
if (jvm->AttachCurrentThread(&env, NULL) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
return NULL;
} else {
// Success : Attached and obtained JNIEnv!
return env;
case JNI_EDETACHED :
// Thread not attached
// TODO : If calling AttachCurrentThread() on a native thread
// must call DetachCurrentThread() in future.
// see: http://developer.android.com/guide/practices/design/jni.html
if (jvm->AttachCurrentThread(&env, NULL) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
return NULL;
} else {
// Success : Attached and obtained JNIEnv!
return env;
}
case JNI_EVERSION :
// Cannot recover from this error
LOGD("JNI interface version 1.4 not supported");
default :
LOGD("Failed to get the environment using GetEnv()");
return NULL;
}
case JNI_EVERSION :
// Cannot recover from this error
LOGD("JNI interface version 1.4 not supported");
default :
LOGD("Failed to get the environment using GetEnv()");
return NULL;
}
}
jclass _getClassID(const char *className, JNIEnv *env) {
if (NULL == className) {
return NULL;
}
jclass ret = env->FindClass(className);
if (!ret) {
LOGD("Failed to find class of %s", className);
}
return ret;
jclass _getClassID(const char *className) {
if (NULL == className) {
return NULL;
}
jstring _jstrClassName = cocos2d::JniHelper::loadclassMethod.env->NewStringUTF(className);
// explicit cast to jclass, since the returned object
jobject _clazzObject = cocos2d::JniHelper::loadclassMethod.env->CallObjectMethod(cocos2d::JniHelper::classloader,
cocos2d::JniHelper::loadclassMethod.methodID,
_jstrClassName);
jclass _clazz = cocos2d::JniHelper::loadclassMethod.env->GetObjectClass(_clazzObject);
if (NULL == _clazz) {
LOGD("Classloader failed to find class of %s", className);
}
cocos2d::JniHelper::loadclassMethod.env->DeleteLocalRef(_jstrClassName);
return _clazz;
}
namespace cocos2d {
JavaVM* JniHelper::_psJavaVM = NULL;
JniMethodInfo JniHelper::loadclassMethod = {NULL, NULL, NULL};
jobject JniHelper::classloader = NULL;
JavaVM* JniHelper::getJavaVM() {
pthread_t thisthread = pthread_self();
@ -100,10 +107,37 @@ namespace cocos2d {
return _psJavaVM;
}
void JniHelper::setJavaVM(JavaVM *javaVM) {
void JniHelper::setJavaVM(JavaVM *javaVM, jobject nativeActivityInstance) {
pthread_t thisthread = pthread_self();
LOGD("JniHelper::setJavaVM(%p), pthread_self() = %X", javaVM, thisthread);
_psJavaVM = javaVM;
if (!setClassLoader(nativeActivityInstance)) {
LOGD("FAIL FAIL FAIL! Could not obtain Java class loader for application code");
}
}
bool JniHelper::setClassLoader(jobject nativeactivityinstance) {
JniMethodInfo _getclassloaderMethod;
if (!JniHelper::getMethodInfo(_getclassloaderMethod,
"android/app/NativeActivity",
"getClassLoader",
"()Ljava/lang/ClassLoader;")) {
return false;
}
jobject _c = _getclassloaderMethod.env->CallObjectMethod(nativeactivityinstance,
_getclassloaderMethod.methodID);
JniMethodInfo _m;
if (!JniHelper::getMethodInfo(_m,
"java/lang/ClassLoader",
"loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;")) {
return false;
}
JniHelper::classloader = _c;
JniHelper::loadclassMethod = _m;
}
bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo,
@ -122,7 +156,7 @@ namespace cocos2d {
return false;
}
jclass classID = _getClassID(className, pEnv);
jclass classID = _getClassID(className);
if (! classID) {
LOGD("Failed to find class %s", className);
return false;
@ -155,7 +189,7 @@ namespace cocos2d {
return false;
}
jclass classID = _getClassID(className, pEnv);
jclass classID = _getClassID(className);
if (! classID) {
LOGD("Failed to find class %s", className);
return false;

View File

@ -40,14 +40,26 @@ typedef struct JniMethodInfo_
class CC_DLL JniHelper
{
public:
static void setJavaVM(JavaVM *javaVM, jobject nativeActivitInstance);
static JavaVM* getJavaVM();
static void setJavaVM(JavaVM *javaVM);
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getStaticMethodInfo(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode);
static std::string jstring2string(jstring str);
static JniMethodInfo loadclassMethod;
static jobject classloader;
private:
static JavaVM *_psJavaVM;
static bool setClassLoader(jobject nativeActivityInstance);
};
NS_CC_END

View File

@ -56,21 +56,13 @@ struct engine {
#include "shaders/CCShaderCache.h"
#include "textures/CCTextureCache.h"
extern "C" void cocos_android_app_init(void);
void cocos_android_app_init(void);
typedef struct cocos_dimensions {
int w;
int h;
} cocos_dimensions;
static void jnihelper_init(JavaVM* vm) {
LOGI("jnihelper_init(...)");
pthread_t thisthread = pthread_self();
LOGI("pthread_self() = %X", thisthread);
cocos2d::JniHelper::setJavaVM(vm);
}
static void cocos_init(cocos_dimensions d, AAssetManager* assetmanager) {
LOGI("cocos_init(...)");
pthread_t thisthread = pthread_self();
@ -259,7 +251,7 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
cocos_dimensions d = engine_init_display(engine);
if ((d.w > 0) &&
(d.h > 0)) {
jnihelper_init(app->activity->vm);
cocos2d::JniHelper::setJavaVM(app->activity->vm, app->activity->clazz);
cocos_init(d, app->activity->assetManager);
}