Hello,阳光柠檬! 养成记录笔记的好习惯

JNI层C++线程回调Java函数示例

2016-03-17
 

Native.java

package com.ticktick.jnicallback;

import android.util.Log;

public class Native {
	
	public native void nativeInitilize();
	
	public native void nativeThreadStart();
	public native void NativeThreadStop();
	
	//this function is callback by native code
	public void onNativeCallback( int count ) {
		Log.d("Native","onNativeCallback count="+count);
	}
	
	static {
    	System.loadLibrary("native");
    }
}

外部JAVA类的调用:

	private Native mNative = new Native();
	
	mNative.nativeInitilize();
	mNative.nativeThreadStart();

Native.c

#include <jni.h>
#include <pthread.h>
#include <android/log.h>

#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG,"Native",__VA_ARGS__)

JavaVM * gJavaVM;
jobject  gJavaObj;

static volatile int gIsThreadExit = 0;

static void* native_thread_exec(void *arg) {

	JNIEnv *env;

	//从全局的JavaVM中获取到环境变量
	(*gJavaVM)->AttachCurrentThread(gJavaVM,&env, NULL);

	//获取Java层对应的类
	jclass javaClass = (*env)->GetObjectClass(env,gJavaObj);
	if( javaClass == NULL ) {
		LOG("Fail to find javaClass");
		return 0;
	}

	//获取Java层被回调的函数
	jmethodID javaCallback = (*env)->GetMethodID(env,javaClass,"onNativeCallback","(I)V");
	if( javaCallback == NULL) {
		LOG("Fail to find method onNativeCallback");
		return 0;
	}

	LOG("native_thread_exec loop enter");

	int count = 0;

	//线程循环
	while(!gIsThreadExit) {

		//回调Java层的函数
		(*env)->CallVoidMethod(env,gJavaObj,javaCallback,count++);

		//休眠1秒
		sleep(1);
	}

	(*gJavaVM)->DetachCurrentThread(gJavaVM);

	LOG("native_thread_exec loop leave");
}

/*
 * Class:     com_ticktick_jnicallback_Native
 * Method:    nativeInitilize
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_ticktick_jnicallback_Native_nativeInitilize(JNIEnv *env, jobject thiz) {

	//注意,直接通过定义全局的JNIEnv和jobject变量,在此保存env和thiz的值是不可以在线程中使用的

	//线程不允许共用env环境变量,但是JavaVM指针是整个jvm共用的,所以可以通过下面的方法保存JavaVM指针,在线程中使用
	(*env)->GetJavaVM(env,&gJavaVM);

	//同理,jobject变量也不允许在线程中共用,因此需要创建全局的jobject对象在线程中访问该对象
	gJavaObj = (*env)->NewGlobalRef(env,thiz);
}

/*
 * Class:     com_ticktick_jnicallback_Native
 * Method:    nativeThreadStart
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_ticktick_jnicallback_Native_nativeThreadStart(JNIEnv *env, jobject thiz) {

	gIsThreadExit = 0;

	//通过pthread库创建线程
	pthread_t threadId;
	if( pthread_create(&threadId,NULL,native_thread_exec,NULL) != 0 ) {
		LOG("native_thread_start pthread_create fail !");
		return;
	}

	LOG("native_thread_start success");
}

/*
 * Class:     com_ticktick_jnicallback_Native
 * Method:    NativeThreadStop
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_ticktick_jnicallback_Native_NativeThreadStop(JNIEnv *env, jobject thiz) {
	gIsThreadExit = 1;
	LOG("native_thread_stop success");
}


Similar Posts

上一篇 Template模式

Comments