在上一篇的基础上,添加在C++代码中回调java方法。
代码如下:
Demo.java 中添加callback函数, 打印一条log.
package com.example.scarecrow.dynamicregisterjni; import android.util.Log; public class Demo { public static final String TAG = "Demo"; static { System.loadLibrary("JniTest"); Log.d(TAG, "dynamic lib loaded"); } public static native String sayHello(); public static void callback(String message) { Log.d(TAG, message); } }
JniTest.cpp 中添加myCallBack方法,在myDynamicJNI中调用,传个字符串回到JAVA。注意:java端的方法是static的话,一定要用GetStaticMethodID和CallStaticVoidMethod。
// // Created by yuany on 6/5/18. // #include <jni.h> #include "android/log.h" #include <cassert> #define LOG_TAG "C_TAG" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) //native method void myCallBack (JNIEnv *env, jclass jobj) { LOGD("myCallBack"); jclass clazz; //找到声明native方法的类 clazz = env->FindClass("com/example/scarecrow/dynamicregisterjni/Demo"); if(clazz == NULL){ LOGD("Findclass error"); return; } LOGD("Findclass succeed"); //寻找class里面的方法 jmethodID callbackID = env->GetStaticMethodID(clazz, "callback", "(Ljava/lang/String;)V"); if(callbackID==0){ LOGD("find callback error"); return; } LOGD("find callback "); jstring result = env->NewStringUTF("this is a callback from C++ codes"); //invoke callback method env->CallStaticVoidMethod(jobj,callbackID, result); } //native method jstring myDynamicJNI (JNIEnv *env, jclass jobj) { LOGD("myDynamicJNI"); //invoke callback method myCallBack(env, jobj); return env->NewStringUTF("This is my first dynamic JNI test"); } /*需要注册的函数列表,放在JNINativeMethod 类型的数组中, 以后如果需要增加函数,只需在这里添加就行了 参数: 1.java代码中用native关键字声明的函数名字符串 2.签名(传进来参数类型和返回值类型的说明) 3.C/C++中对应函数的函数名(地址) */ static JNINativeMethod getMethods[] = { {"sayHello","()Ljava/lang/String;",(void*)myDynamicJNI}, }; //此函数通过调用JNI中 RegisterNatives 方法来注册我们的函数 static int registerNativeMethods(JNIEnv* env, const char* className,JNINativeMethod* getMethods,int methodsNum){ LOGD("registerNativeMethods"); jclass clazz; //找到声明native方法的类 clazz = env->FindClass(className); if(clazz == NULL){ return JNI_FALSE; } LOGD("after Findclass"); //注册函数 参数:java类 所要注册的函数数组 注册函数的个数 if(env->RegisterNatives(clazz,getMethods,methodsNum) < 0){ return JNI_FALSE; } LOGD("after RegisterNatives"); return JNI_TRUE; } //回调函数 在这里面注册函数 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ LOGD("JNI_OnLoad"); JNIEnv* env = NULL; //判断虚拟机状态是否有问题 if(vm->GetEnv((void**)&env,JNI_VERSION_1_6)!= JNI_OK){ return -1; } assert(env != NULL); //指定类的路径,通过FindClass 方法来找到对应的类 const char* className = "com/example/scarecrow/dynamicregisterjni/Demo"; //开始注册函数 registerNatives -》registerNativeMethods -》env->RegisterNatives if(!registerNativeMethods(env,className,getMethods, 1)){ return -1; } //返回jni 的版本 return JNI_VERSION_1_6; }
关于JNI更多详细内容可以参考https://blog.csdn.net/rainteen/article/details/43376337#t0