楼主开发中有这样的情况,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代码回调使用。