Android :JNI 回调demo
一、AndroidStudioProjects\jnicallbackdemo\app\src\main\java\com\example\jnicallbackdemo\MainActivity.java
package com.example.jnicallbackdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Callbacktest m_nextouch =new Callbacktest();
int n=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// m_nextouch.start();
start();
}
static {
System.loadLibrary("callback");
}
public native void start();
public void callback(String str){
System.out.println("information from jni callback:"+str+" number="+n);
n++;
}
}
二、AndroidStudioProjects\jnicallbackdemo\app\src\main\jni\com_example_jnicallbackdemo_MainActivity.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnicallbackdemo_MainActivity */
#ifndef _Included_com_example_jnicallbackdemo_MainActivity
#define _Included_com_example_jnicallbackdemo_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnicallbackdemo_MainActivity
* Method: start
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_jnicallbackdemo_MainActivity_start
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
三、AndroidStudioProjects\jnicallbackdemo\app\src\main\jni\com_example_jnicallbackdemo_Callbacktest.c
#include<stdlib.h>
#include<pthread.h>
#include<jni.h>
#include<android/log.h>
//#include "com_example_jnicallbackdemo_Callbacktest.h"
#include "com_example_jnicallbackdemo_MainActivity.h"
#define LOG_TAG "JNICALLBACK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
jmethodID mid;
jclass objclass;
jobject mobj;
pthread_t thread;
JavaVM *m_vm;
//初始化的时候会调进来一次,在这个方法里持有jvm的引用
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){
m_vm=vm;
JNIEnv* env = NULL;
jint result = -1;
if(m_vm){
LOGD("m_vm init success");
}else{
LOGD("m_vm init failed");
}
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK){
return result;
}
return JNI_VERSION_1_4;
}
JNIEnv* getJNIEnv(int* needsDetach){
JNIEnv* env = NULL;
jint result = -1;
if ((*m_vm)->GetEnv(m_vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK){
int status = (*m_vm)->AttachCurrentThread(m_vm, &env, 0);
if (status < 0){
LOGD("failed to attach current thread");
return NULL;
}
*needsDetach = 1;
}
LOGD("GetEnv Success");
return env;
}
void *thread_run(){
LOGD("thread start");
int needsDetach;
JNIEnv *evn=getJNIEnv(&needsDetach);
LOGD("start noop callback");
while(1)
{
jstring jstr = (*evn) -> NewStringUTF(evn, "I am from JNI !");
LOGD("invoke callback");
(*evn)->CallVoidMethod(evn, mobj, mid, jstr);
jthrowable exception = (*evn)->ExceptionOccurred(evn);
if (exception) {
(*evn)->ExceptionDescribe(evn);
}
usleep(1000*250);
(*evn) -> DeleteLocalRef(evn, jstr);
}
if(needsDetach)
(*m_vm)->DetachCurrentThread(m_vm);
}
//JNIEXPORT void JNICALL Java_com_example_jnicallbackdemo_Callbacktest_start(JNIEnv *evn, jobject object){
JNIEXPORT void JNICALL Java_com_example_jnicallbackdemo_MainActivity_start(JNIEnv *evn, jobject object){
LOGD("call start");
//在子线程中不能这样用
//jclass tclass = (*evn)->FindClass(evn, "com/example/jnicallbackdemo/CallbackTest");
//这种写法可以用在子线程中
objclass=(*evn)->GetObjectClass(evn, object);
mid = (*evn)->GetMethodID(evn, objclass, "callback", "(Ljava/lang/String;)V");
//JNI 函数参数中 jobject 或者它的子类,其参数都是 local reference。Local reference 只在这个 JNI函数中有效,JNI函数返回后,引用的对象就被释放,它的生命周期就结束了。若要留着日后使用,则需根据这个 local reference 创建 global reference。Global reference 不会被系统自动释放,它仅当被程序明确调用 DeleteGlobalReference 时才被回收。(JNI多线程机制)
mobj=(*evn)->NewGlobalRef(evn, object);
pthread_create(&thread, NULL, thread_run, NULL);
}
四、代码图
五、运行效果
六、源码下载路径:https://download.csdn.net/download/qq_37858386/12890125