使用NDK進行JNI編程與實踐五:使用C/C++代碼回調java類中方法

一、需求:
我們將本地方法和被調用的java類公共方法放在同一個類中,本地方法用於調用C/C++代碼,在C/C++代碼中實現邏輯,用於調用java中公共方法,公共方法中可添加打印之類的確認是否調用成功,邏輯梳理:

java native method ---> C/C++ method ---> java public method

二、示例:

  1. 使用C++代碼回調java的add函數:
    /* JNI回調java函數:調用addSum */
    public native void callAddSum();
    /* java公共函數:addSum */
    public void addSum(int x, int y){
        Log.e("jiyi", "addSum: " + (x + y));
    }

c++函數:

/* 回調java類中的addSum函數:傳入兩個int型參數 */
JNIEXPORT void JNICALL Java_com_example_jnitest_JNITest_callAddSum
        (JNIEnv *env, jobject jobj)
{
    /* 通過包名找到Java中的類名 */
    jclass clazz = env->FindClass("com/example/jnitest/JNITest");
    if (clazz == 0)
    {
        LOGE("failed to find class JNITest");
    }
    else
    {
        LOGE("find class JNITest succeed!");
    }

    /* 獲取java類中方法id:參數一爲類對象,參數二爲java中方法名,參數三爲方法唯一簽名 */
    jmethodID jId = env->GetMethodID(clazz, "addSum", "(II)V");
    if (jId == 0)
    {
        LOGE("failed to find method in java!");
    }
    else
    {
        LOGE("find method succeed!");
    }

    /* 調用java中的方法 */
    env->CallVoidMethod(jobj, jId, 10, 20);
}
  1. 使用C/C++代碼回調callStrFromJni函數:
    /* JNI回調java函數:調用StrFromJni */
    public native void callStrFromJni();
    /* java公共函數:addSum */
    public void StrFromJni(String str){
        Log.e("jiyi", "StrFromJni: " + str);
    }

C++代碼:

/* 回調java類中的StrFromJni方法:傳入參數String */
JNIEXPORT void JNICALL Java_com_example_jnitest_JNITest_callStrFromJni
        (JNIEnv *env, jobject jobj)
{
    /* 通過包名找到Java中的類名 */
    jclass clazz = env->FindClass("com/example/jnitest/JNITest");
    if (clazz == 0)
    {
        LOGE("failed to find class JNITest");
    }
    else
    {
        LOGE("find class JNITest succeed!");
    }

    /* 獲取java類中方法id:參數一爲類對象,參數二爲java中方法名,參數三爲方法唯一簽名 */
    jmethodID jId = env->GetMethodID(clazz, "StrFromJni", "(Ljava/lang/String;)V");
    if (jId == 0)
    {
        LOGE("failed to find method in java!");
    }
    else
    {
        LOGE("find method succeed!");
    }

    /* 調用java中的方法 */
    env->CallVoidMethod(jobj, jId, env->NewStringUTF("I'm from JNI!"));
}

二、總結:
使用C/C++代碼回調java中方法其實跟修改java中的屬性邏輯是一樣的,都是先獲取java對象的字節碼,然後獲取Java方法的id之後,再回調對應的java方法。

代碼路徑:

https://github.com/jiyi666/apk-demo/tree/master/JNITest
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章