一、需求:
我们将本地方法和被调用的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