近日,我们WifiDisplay的项目中,有需要用到C call Java的代码,我不太能够懂得如何能够实现C call Java,所以我就向我们公司的一帮牛人请教了下,只是简单的写了一个C call Java的实例。
代码:
1.我首先是在java中写了一个调用C层代码的方法,名字叫nativeSetup的方法
public static native void nativeSetup(Object obj);
之后在java中的activity中的onCreate方法中调用它:
nativeSetup(this);
通过这个方法将一个activity的对象传入C层中;
2.在C层中,通过实现nativeSetup(Object),来得到上层Java代码中的对象,从而能够得到methodID,再通过CallStaticMethod方法,调用Java层的方法,具体实现:
static jobject player = NULL;
static JavaVM* gJavaVM = NULL;
extern "C" { JNIEXPORT void JNICALL Java_com_uv_renderer_ProvisionActivity_nativeSetup(JNIEnv *env, jobject obj, jobject param); }JNIEXPORT void JNICALL Java_com_uv_renderer_ProvisionActivity_nativeSetup(JNIEnv *env, jobject obj, jobject param){player = env->NewGlobalRef(param);env->GetJavaVM(&gJavaVM);if (env->ExceptionOccurred()) {
return; }if(gJavaVM == NULL) { env->GetJavaVM(&gJavaVM); if (env->ExceptionOccurred()) { return; } }
if (env->ExceptionOccurred()) { return; }
__android_log_print(ANDROID_LOG_INFO, "ProvisionActiity","C : ProvisionActiity : nativeSetup called");
}void callVoidMethod(char* ch){JNIEnv* myEnv = NULL; gJavaVM->AttachCurrentThread(&myEnv, NULL); jclass cls = myEnv->GetObjectClass(player); jmethodID method = myEnv->GetStaticMethodID(cls, "callVoidMethod","(Ljava/lang/String;)V");if (myEnv != NULL && cls != NULL && method != NULL) { __android_log_print(ANDROID_LOG_INFO, "ProvisionActivity","C : ProvisionActivity : callVoidMethod : called begin"); jstring str = toJString(myEnv, ch); myEnv->CallStaticVoidMethod(cls, method, str); if (myEnv->ExceptionOccurred()) { gJavaVM->DetachCurrentThread(); return; } gJavaVM->DetachCurrentThread(); }
__android_log_print(ANDROID_LOG_INFO, "ProvisionActivity","C : ProvisionActivity : callVoidMethod : called end");
}int callIntMethod(){__android_log_print(ANDROID_LOG_INFO, "ProvisionActivityC : ProvisionActivity : callIntMethod : called start"); int intNumber= -1;JNIEnv* myEnv = NULL; gJavaVM->AttachCurrentThread(&myEnv, NULL); jclass cls = myEnv->GetObjectClass(player); jmethodID methodId = myEnv->GetStaticMethodID(cls, "callIntMethod", "()I");
if (myEnv != NULL && cls != NULL && methodId != NULL) { intNumber = myEnv->CallStaticIntMethod(cls, methodId); if (myEnv->ExceptionOccurred()) { gJavaVM->DetachCurrentThread(); return -1; } gJavaVM->DetachCurrentThread();
} __android_log_print(ANDROID_LOG_INFO, "ProvisionActivity","C : ProvisionActivity : callIntMethod : called end"); return intNumber;
}const char* callStringMethod(){__android_log_print(ANDROID_LOG_INFO, "ProvisionActivty","C : ProvisionActivity : callStringMethod : called start"); const char* ch = NULL; JNIEnv* myEnv = NULL; gJavaVM->AttachCurrentThread(&myEnv, NULL); jclass cls = myEnv->GetObjectClass(player);jmethodID methodId = myEnv->GetStaticMethodID(cls, "callStringMethod", "()Ljava/lang/String;"); jstring str =NULL;
if (myEnv != NULL && cls != NULL && methodId != NULL) {
str = (jstring)(myEnv->CallStaticObjectMethod(cls, methodId));
if (str != NULL) ch = myEnv->GetStringUTFChars(str, 0);
if (myEnv->ExceptionOccurred()) { gJavaVM->DetachCurrentThread(); return NULL; } gJavaVM->DetachCurrentThread();
}__android_log_print(ANDROID_LOG_INFO, "ProvisionActivty","C : ProvisionActivity : callStringMethod : called end");return ch;}void callVoidMethod(char* first,char* second){__android_log_print(ANDROID_LOG_INFO, "ProvisionActivty","C : ProvisionActivity : callVoidMethod(char*,char*) : called start");if (player== NULL) { return; } JNIEnv* myEnv = NULL; gJavaVM->AttachCurrentThread(&myEnv, NULL);
jclass cls = myEnv->GetObjectClass(player); jmethodID method = myEnv->GetStaticMethodID(cls, "callVoidMethod","(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V"); if (myEnv && cls && method) { jstring jarg1 = myEnv->NewStringUTF((const char*) first); jstring jarg2 = myEnv->NewStringUTF((const char*) second); myEnv->CallStaticVoidMethod(cls, method, player, jarg1, jarg2); if (myEnv->ExceptionOccurred()) { gJavaVM->DetachCurrentThread(); return; } gJavaVM->DetachCurrentThread(); }
__android_log_print(ANDROID_LOG_INFO, "ProvisionActivty","C : ProvisionActivity : callVoidMethod(char*,char*) : called end");}
好了,C call Java的调用就已经结束了。最后再附个将jstring转化为char*的方法:
jstring toJString(JNIEnv* env, char* pat) { __android_log_print(ANDROID_LOG_INFO, "ProvisionActivity","C : ProvisionActivity : toJString called start");jclass strClass = env->FindClass("java/lang/String"); jmethodID ctorID = env->GetMethodID(strClass, "<init>","([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat); jstring encoding = env->NewStringUTF("utf-8");__android_log_print(ANDROID_LOG_INFO, "ProvisionActivity","C : ProvisionActivity : toJString called end");return (jstring) env->NewObject(strClass, ctorID, bytes, encoding);}