1. 程式人生 > >Android 在JNI主執行緒呼叫Java方法

Android 在JNI主執行緒呼叫Java方法

1. C++ 全域性呼叫Java方法

1.1 C++主執行緒呼叫Java方法

Android C++多執行緒-建立子執行緒中演示了在 Java 層呼叫 native 層的方法,但是如何在 native 層去呼叫 Java 層的方法呢?
下面這個類,我們想在呼叫 callJavaMethodOnCPPMainThread 方法之後,然後在 native 層回撥 JniThreadDemoonSuccess 的方法。

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日晚