一、需求:
我們將本地方法和被調用的java類公共方法放在同一個類中,本地方法用於調用C/C++代碼,在C/C++代碼中實現邏輯,用於調用java中公共方法,公共方法中可添加打印之類的確認是否調用成功,邏輯梳理:
java native method ---> C/C++ method ---> java public method
二、示例:
- 使用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);
}
- 使用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