接着上一節,這一節來寫一下如何用本地代碼調用java函數。首先在MainActivity.java聲明一個本地方法
public static native void callBack(MainActivity activity);
然後將生成的代碼移到cpp文件中
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_callBack
(JNIEnv *env, jobject,jobject mainActivity){
}
上面有一個jobject類型的參數,這個參數是自動生成的,如果這個函數是非static的則這個參數位置就是jobject類型的,代表調用此函數的類的實例的引用,如果這個函數是靜態的則這個位置大參數類型爲jclass,代表調用此函數的類的引用。出於方便我們就調用MainActivity的函數,在MainActivity.java 加一個供調用的函數
void onCallBack(int flag){
Log.i(TAG, "onCallBack: "+flag);
}
一切就緒,接下來就來看看如何在jni層實現調用
首先根據參數mainActivity 來獲取java的class類.jni層用jclass表示java的class
jclass mainClass = env->GetObjectClass(mainActivity);
然後再根據mainClass來獲取jmethodID,jmethodID表示java方法
jmethodID jmethodID1 = env->GetMethodID(mainClass,"onCallBack","(I)V");
GetMethodID()裏參數的意思是在mainClass所代表的類裏面找到一個名叫onCallBack的函數他只有一個int類型的參數,他的返回值值是void.
獲取到methodId之後就可以調用javac函數了
env->CallVoidMethod(mainActivity,jmethodID1,101);
調用之後還要delete掉本地對象,因爲jni的申請本地對象資源是有限的,所以要儘量在本地對象不用的時候delete掉,以便節省資源。
env->DeleteLocalRef(mainClass);
完整代碼如下
JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_callBack
(JNIEnv *env, jobject,jobject mainActivity){
jclass mainClass = env->GetObjectClass(mainActivity);
if(mainClass == nullptr)
return ;
jmethodID jmethodID1 = env->GetMethodID(mainClass,"onCallBack","(I)V");
if(jmethodID1 == nullptr)
return;
env->CallVoidMethod(mainActivity,jmethodID1,101);
env->DeleteLocalRef(mainClass);
}