Android 在JNI主執行緒呼叫Java方法
阿新 • • 發佈:2019-01-02
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日晚