JNI初步(二)c呼叫java方法

2020-09-21 23:00:25

1.寫Jni類  並且在下面寫好需要被c呼叫的方法方法體也寫好

public class Jni {

    {
        System.loadLibrary("cCallJava");
    }

    public native int addCallBack();

    public int add(int a, int b) {
        Log.i("godv", "a+b = " + a + b);
        return a + b;
    }
}

2.利用 javah 生成對應的 .h 檔案 並且新建 .c 檔案實現callBack方法

注意引入標頭檔案 #include "com_godv_ccalljava_Jni.h"

獲取方法簽名

我這裡是在如徑 AndroidStudioProjects\Hello\ccalljava\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes

執行  javap -s com.godv.ccalljava.Jni

方法簽名如下:

#include "com_godv_ccalljava_Jni.h"

#include <android/log.h>
#define LOG_TAG "godv"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

JNIEXPORT jint JNICALL Java_com_godv_ccalljava_Jni_addCallBack
  (JNIEnv * env, jobject jobj)
  {
       /**
        * 用法 :獲取java類的 位元組碼檔案
        * 引數1 :env
        * 引數2 :路徑
        * 返回值 :jclass
        */
        jclass jclazz = (*env)->FindClass(env,"com/godv/ccalljava/Jni");
       /**
        * 用法 :獲取java方法的 methodid
        * 引數1 :env
        * 引數2 :位元組碼檔案
        * 引數3 :方法名
        * 引數4 :方法簽名
        // AndroidStudioProjects\Hello\ccalljava\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes
        * 返回值 :jmethodID
        */
       jmethodID jids = (*env)->GetMethodID(env,jclazz,"add","(II)I");
       /**
        * 用法 : 獲得java類範例
        * 引數1 :env
        * 引數2 :位元組碼檔案
        * 返回值 : jobject型別的 java範例物件
       */
       jobject jni = (*env)->AllocObject(env,jclazz);
       /**
        * 用法 : jni 呼叫java方法
        * 引數1 :env
        * 引數2 :java類範例
        * 引數3 : java方法ID
        * 其餘引數為 該java方法所需引數
        */
       LOGD("返回值為 %d",6+7);
       return (*env)->CallIntMethod(env,jni,jids,6,7);

  }

3.在Java這面呼叫即可

public void add(View view) {
        int i = jni.addCallBack();
        Log.i("godv", "" + i);
    }

注意 : 別忘了設定 ndk   設定log

ndk{
            moduleName "cCallJava"  //so   檔案   lib+moduleName+.so
            abiFilters 'armeabi' , 'armeabi','x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' //cpu型別
            ldLibs 'log'
        }

一個c返回字串的例子

JNIEXPORT jint JNICALL Java_com_godv_ccalljava_Jni_strCallBack
    (JNIEnv * env, jobject jobj)
    {
        jclass jclazz = (*env)->FindClass(env,"com/godv/ccalljava/Jni");
        jmethodID jids = (*env)->GetMethodID(env,jclazz,"str","(Ljava/lang/String;)V");
        jobject jni = (*env)->AllocObject(env,jclazz);
        jstring str = (**env).NewStringUTF(env,"Im godv !");
        (*env)->CallVoidMethod(env,jni,jids,str);
    }
public void str(String s) {
        Log.i("godv", "c中輸入的字串為 = " + s);
    }

一個呼叫靜態方法的例子

JNIEXPORT void JNICALL Java_com_godv_ccalljava_Jni_staticCallBack
 (JNIEnv * env, jobject jobj)
 {
     jclass jclazz = (*env)->FindClass(env,"com/godv/ccalljava/Jni");
     jmethodID jids = (*env)->GetStaticMethodID(env,jclazz,"sta","(Ljava/lang/String;)V");
     jstring str = (**env).NewStringUTF(env,"Im static godv !");
     (*env)->CallStaticVoidMethod(env,jclazz,jids,str);
 }
public static void sta(String s) {
        Log.i("godv", "靜態方法 : c中輸入的字串為 = " + s);
    }