在JNI代码中异步回调Java层方法

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值