午夜稻草人

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

在上一篇的基础上,添加在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

posted on 2018-06-07 18:59  午夜稻草人  阅读(901)  评论(0编辑  收藏  举报