Android 在JNI主線程調(diào)用Java方法

1. C++ 全局調(diào)用Java方法

1.1 C++主線程調(diào)用Java方法

Android C++多線程-創(chuàng)建子線程中演示了在 Java 層調(diào)用 native 層的方法,但是如何在 native 層去調(diào)用 Java 層的方法呢?
下面這個(gè)類,我們想在調(diào)用 callJavaMethodOnCPPMainThread 方法之后,然后在 native 層回調(diào) JniThreadDemoonSuccess 的方法。

public class JniThreadDemo {

    private static final String TAG = JniThreadDemo.class.getSimpleName();

    static {
        System.loadLibrary("native-thread-lib");
    }
    //在主線程中調(diào)用 onSuccess 方法
    public native void callJavaMethodOnCPPMainThread();

    public void onSuccess(String msg) {
        Log.i(TAG, "JNI 回調(diào) Java層 onSuccess 方法:" + msg);
    }
}

實(shí)際的調(diào)用函數(shù)

public void callJavaMethodOnCppMainThread(View view) {
    JniThreadDemo jniThreadDemo = new JniThreadDemo();
    //在主線程調(diào)用
    jniThreadDemo.callJavaMethodOnCPPMainThread();
}

上面演示的只是調(diào)用了 jniThreadDemo.callJavaMethodOnCPPMainThread 函數(shù),下面我們來看看如何在 native 層去回調(diào) onSuccess 函數(shù)的。

1.2 native 回調(diào) Java 層函數(shù)的過程

這個(gè)過程類似于 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 時(shí)如何調(diào)用 Java 層的函數(shù)的。

1.2.1 獲取到 jclass

根據(jù) jobject 獲取到 jclass

jclass jclz = env->GetObjectClass(instance);

1.2.2 獲取到 jmethodid

因?yàn)橐卣{(diào) Java 層的 onSuccess 函數(shù),所以需要在這里定義具體要調(diào)用的函數(shù)名字和函數(shù)簽名,具體如何獲取函數(shù)簽名,請點(diǎn)擊JNI函數(shù)簽名來了解

jmethodID jmethod = env->GetMethodID(jclz, "onSuccess", "(Ljava/lang/String;)V");

1.2.3 調(diào)用 Java 方法

jenv->CallVoidMethod(jobj, jmid, code, jmsg) 

下面是 C++ 的全部代碼

//在 c++ 主線程調(diào)用 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. 調(diào)用函數(shù)
    env->CallVoidMethod(jobj, jmethod, jmsg);

    env->DeleteLocalRef(jmsg);

}

小結(jié):通過以上示例代碼,我們就可以實(shí)現(xiàn)在 Java 層調(diào)用 JNI 層函數(shù)執(zhí)行完某一些操作之后,然后 JNI 層再告訴 Java 層具體的操作結(jié)果,也就是調(diào)用 Java 層的函數(shù)。

項(xiàng)目地址:
https://github.com/liaowjcoder/Jni4Android

記錄于 2018年11月10日晚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容