弱龄寄事外,委怀在琴书。这篇文章主要讲述Android开发实践:JNI层线程回调Java函数示例相关的知识,希望能为你提供帮助。
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/1358558
JNI是java Native Interface的缩写,是Java平台的重要特性,使得Java代码可以方便地与C/C++代码编译生成的动态链接库进行交互。本文主要给出一份示例代码(工程文件见附件),描述如何在android的JNI层开启一个线程,并在线程中回调Java层的函数。
代码主要分为Java层(java代码)和JNI层(c语言代码),首先看看Java层的代码(Native.java)。
文章图片
如上所示,Java层与JNI层的接口代码主要封装在Native类中,该类定义了三个native函数,分别完成jni库的初始化,调用jni层开启线程,调用jni层关闭线程等功能。并且提供一个回调函数(onNativeCallback),供jni层调用,并在回调函数中打印count的值。
再看看JNI层是如何开启线程并回调Java层的(native.c),关键的地方都在代码中进行了注释:
native C实现:
1. 头文件包含和全局变量的定义
文章图片
2. 初始化函数的实现
文章图片
3. 开启关闭线程的实现
文章图片
4. 线程的实现(关键)
文章图片
native C++实现
#include < jni.h>
#include < android/log.h>
#include < pthread.h>
#include < unistd.h>
#define TAG "JniNative"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
JavaVM *gJavaVM;
jobject gJavaObj;
int volatile gIsThreadStop = 0;
static const char *classPath = "com/jni/test/JniNativeCallback";
static void* native_thread_exec(void *arg)
{
LOGI("nativeThreadExec");
JNIEnv *env;
//get env From gJavaVm
gJavaVM-> AttachCurrentThread(& env,NULL);
//get Java class by classPath
// jclass thiz = env-> FindClass(classPath);
jclass thiz = env-> GetObjectClass(gJavaObj);
//get Java method from thiz
jmethodID nativeCallback = env-> GetMethodID(thiz,"nativeCallback","(I)V");
int count = 0;
while(!gIsThreadStop)
{
sleep(2);
//env-> CallVoidMethod(thiz,nativeCallback,count++);
env-> CallVoidMethod(gJavaObj,nativeCallback,count++);
}
gJavaVM-> DetachCurrentThread();
LOGI("thread stoped");
}
JNIEXPORT void JNICALL native_init(JNIEnv *env,jobject thiz)
{
LOGI("native_init");
gIsThreadStop = 0;
env-> GetJavaVM(& gJavaVM);
gJavaObj = env-> NewGlobalRef(thiz);
}
JNIEXPORT void JNICALL native_thread_start(JNIEnv *env,jobject jthiz)
{
LOGI("native_thread_start");
gIsThreadStop = 0;
pthread_t id;
if(pthread_create(& id,NULL,native_thread_exec,NULL)!=0)
{
LOGI("native thread create fail");
return;
}
LOGI("native thread creat success");
}
JNIEXPORT void JNICALL native_thread_stop(JNIEnv *env,jobject jthiz)
{
gIsThreadStop = 1;
LOGI("native_thread_stop");
}
static JNINativeMethod methods[] = {
{"nativeInit","()V",(void*)native_init},
{"nativeThreadStart","()V",(void*)native_thread_start},
{"nativeThreadStop","()V",(void*)native_thread_stop}
};
jint JNI_OnLoad(JavaVM *vm, void *reserve)
{
LOGI("JNI_OnLoad");
JNIEnv *env;
if(vm-> GetEnv((void**)& env,JNI_VERSION_1_4)!=JNI_OK)
{
return -1;
}
jclass jthiz = env-> FindClass(classPath);
if(env-> RegisterNatives(jthiz,methods,sizeof(methods)/sizeof(methods[0]))< 0)
{
return -1;
}
return JNI_VERSION_1_4;
}
【Android开发实践(JNI层线程回调Java函数示例)】 由上述代码可以看到,JNI层通过pthread库完成了线程的创建,需要特别注意的是,JNI层的线程中,必须通过全局的JavaVM来获取到环境变量,也必须通过全局的jobject获取java类对象,从而找到java端的函数,进行回调。
推荐阅读
- Work Management Service application in SharePoint 2016
- appium安装
- Android开发之裁切(拍照+相冊)图像并设置头像小结
- Android中的颜色
- 推荐系统--splitting approaches for context-aware recommendation
- 微擎app端上传图片后删除不了图片
- Android之弹出菜单框注冊上下文菜单
- 推荐扔物线的HenCoder Android 开发进阶系列 后期接着更新
- Android ToolBar 使用完全解析