1. C++ 全局调用Java方法
1.1 C++主线程调用Java方法
在 Android C++多线程-创建子线程中演示了在 Java 层调用 native 层的方法,但是如何在 native 层去调用 Java 层的方法呢?
下面这个类,我们想在调用 callJavaMethodOnCPPMainThread
方法之后,然后在 native 层回调 JniThreadDemo
的 onSuccess
的方法。
public class JniThreadDemo {
private static final String TAG = JniThreadDemo.class.getSimpleName();
static {
System.loadLibrary("native-thread-lib");
}
//在主线程中调用 onSuccess 方法
public native void callJavaMethodOnCPPMainThread();
public void onSuccess(String msg) {
Log.i(TAG, "JNI 回调 Java层 onSuccess 方法:" + msg);
}
}
实际的调用函数
public void callJavaMethodOnCppMainThread(View view) {
JniThreadDemo jniThreadDemo = new JniThreadDemo();
//在主线程调用
jniThreadDemo.callJavaMethodOnCPPMainThread();
}
上面演示的只是调用了 jniThreadDemo.callJavaMethodOnCPPMainThread
函数,下面我们来看看如何在 native 层去回调 onSuccess
函数的。
1.2 native 回调 Java 层函数的过程
这个过程类似于 Java 的反射过程,例如下面的例子
public class JniThreadDemo {
public void onSuccess(String msg) {
System.out.println("onSuccess invoke.."+ msg);
}
public static void main(String[] args) {
try {
Class<JniThreadDemo> clz = JniThreadDemo.class;
Method method = clz.getMethod("onSuccess", String.class);
JniThreadDemo jniThreadDemo = clz.newInstance();
method.invoke(jniThreadDemo, "反射");
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面来看一下,Jni 时如何调用 Java 层的函数的。
1.2.1 获取到 jclass
根据 jobject 获取到 jclass
jclass jclz = env->GetObjectClass(instance);
1.2.2 获取到 jmethodid
因为要回调 Java 层的 onSuccess 函数,所以需要在这里定义具体要调用的函数名字和函数签名,具体如何获取函数签名,请点击JNI函数签名来了解
jmethodID jmethod = env->GetMethodID(jclz, "onSuccess", "(Ljava/lang/String;)V");
1.2.3 调用 Java 方法
jenv->CallVoidMethod(jobj, jmid, code, jmsg)
下面是 C++ 的全部代码
//在 c++ 主线程调用 Java 方法。
extern "C"
JNIEXPORT void JNICALL
Java_com_liaowj_jni_thread_JniThreadDemo_callJavaMethodOnCPPMainThread(JNIEnv *env,
jobject jobj) {
//1. 得到 jclass
jclass jclz = env->GetObjectClass(jobj);
//2. 得到 jmethod
jmethodID jmethod = env->GetMethodID(jclz, "onSuccess", "(Ljava/lang/String;)V");
//得到 jstring
char *msg = "Msg From C++ Thread";
jstring jmsg = env->NewStringUTF(msg);
//3. 调用函数
env->CallVoidMethod(jobj, jmethod, jmsg);
env->DeleteLocalRef(jmsg);
}
小结:通过以上示例代码,我们就可以实现在 Java 层调用 JNI 层函数执行完某一些操作之后,然后 JNI 层再告诉 Java 层具体的操作结果,也就是调用 Java 层的函数。
项目地址:
https://github.com/liaowjcoder/Jni4Android
记录于 2018年11月10日晚