楼主开发中有这样的情况,native代码中某回调函数需要回调Java层某方法,由于从c层代码回调时JNIEnv这个指针是取不到的,所以这成了一个问题。
google一下,这个问题还是可以解决的。
1.首先我们需要保存下来一个JavaVM的指针,如下:
static JavaVM* jvm;
在一个init的方法里将这个指针保存下来(可以在JNI_OnLoad()里做)
env->GetJavaVM(&jvm);
2.在需要进行回调的地方
void statusCallbackFunc(const int ret, const std::map<std::string, int>& status_map) { LOGI("[JNI] statusCallbackFunc E ret = %d", ret); if (devStatusCallbackObj) { // get jni environment JNIEnv * env; int status = jvm->GetEnv((void **) &env, JNI_VERSION_1_6); if (status < 0) { status = jvm->AttachCurrentThread(&env, NULL); if (status < 0) { return; } } // find target clazz jclass listActivityClazz = env->GetObjectClass(devStatusCallbackObj); // find target method jmethodID midUpdate = env->GetMethodID(listActivityClazz, "updateDeviceSatatus", "(ILjava/util/HashMap;)V"); jobject ret_map = NULL; if (ret == 0 && status_map.size() > 0) { // create a HashMap obj jclass clzHashMap = env->FindClass("java/util/HashMap"); jmethodID midHashMap = env->GetMethodID(clzHashMap, "<init>", "()V"); ret_map = env->NewObject(clzHashMap, midHashMap); // put all jmethodID midPut = env->GetMethodID(clzHashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); // find Integer clazz jclass clzInteger = env->FindClass("java/lang/Integer"); jmethodID midInteger = env->GetMethodID(clzInteger, "<init>", "(I)V"); std::map<std::string, int>::const_iterator it; for (it = status_map.begin(); it != status_map.end(); ++it) { jstring key = env->NewStringUTF(it->first.c_str()); jobject val = env->NewObject(clzInteger, midInteger, it->second); env->CallObjectMethod(ret_map, midPut, key, val); env->DeleteLocalRef(key); env->DeleteLocalRef(val); } env->DeleteLocalRef(clzInteger); env->DeleteLocalRef(clzHashMap); } // call env->CallVoidMethod(devStatusCallbackObj, midUpdate, ret, ret_map); env->DeleteLocalRef(ret_map); env->DeleteLocalRef(listActivityClazz); LOGI("[JNI] DetachCurrentThread E"); jvm->DetachCurrentThread(); LOGI("[JNI] DetachCurrentThread X"); } status_map.clear(); LOGI("[JNI] statusCallbackFunc X"); }
PS:所谓异步并不准确,这篇文章主要是解决这样的问题:从c代码中回调Java层时,无法获取JNIEnv*。解决方法为先保存一个JavaVM*,提供给c代码回调使用。