Android開發實踐:JNI層線程回調Java函數樣本

來源:互聯網
上載者:User

標籤:volatile   info   rgs   51cto   glob   load   ace   width   va_arg   

原創作品,允許轉載,轉載時請務必以超連結形式標明文章 原始出處 、作者資訊和本聲明。否則將追究法律責任。http://ticktick.blog.51cto.com/823160/1358558

JNI是Java Native Interface的縮寫,是Java平台的重要特性,使得Java代碼可以方便地與C/C++代碼編譯產生的動態連結程式庫進行互動。本文主要給出一份範例程式碼(工程檔案見附件),描述如何在Android的JNI層開啟一個線程,並線上程中回調Java層的函數。

 

代碼主要分為Java層(java代碼)和JNI層(c語言代碼),首先看看Java層的代碼(Native.java)。

 

 

如上所示,Java層與JNI層的介面代碼主要封裝在Native類中,該類定義了三個native函數,分別完成jni庫的初始化,調用jni層開啟線程,調用jni層關閉線程等功能。並且提供一個回呼函數(onNativeCallback),供jni層調用,並在回呼函數中列印count的值。

 

再看看JNI層是如何開啟線程並回調Java層的(native.c),關鍵的地方都在代碼中進行了注釋:

native C實現:

   1. 標頭檔包含和全域變數的定義

           

         

   2. 初始化函數的實現

             

 

   3. 開啟關閉線程的實現

 

                                           

 4. 線程的實現(關鍵)

 

 

native C++實現

#include <jni.h>
#include <android/log.h>
#include <pthread.h>
#include <unistd.h>

#define TAG "JniNative"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)

JavaVM *gJavaVM;
jobject gJavaObj;
int volatile gIsThreadStop = 0;
static const char *classPath = "com/jni/test/JniNativeCallback";

static void* native_thread_exec(void *arg)
{
    LOGI("nativeThreadExec");
    JNIEnv *env;
    //get env From gJavaVm
    gJavaVM->AttachCurrentThread(&env,NULL);
    //get Java class by classPath
//    jclass thiz = env->FindClass(classPath);
    jclass thiz = env->GetObjectClass(gJavaObj);
    //get Java method from thiz
    jmethodID nativeCallback = env->GetMethodID(thiz,"nativeCallback","(I)V");
    int count = 0;
    while(!gIsThreadStop)
    {
        sleep(2);
        //env->CallVoidMethod(thiz,nativeCallback,count++);
        env->CallVoidMethod(gJavaObj,nativeCallback,count++);
    }
    gJavaVM->DetachCurrentThread();
    LOGI("thread stoped");
}


JNIEXPORT void JNICALL native_init(JNIEnv *env,jobject thiz)
{
    LOGI("native_init");
    gIsThreadStop = 0;
    env->GetJavaVM(&gJavaVM);
    gJavaObj = env->NewGlobalRef(thiz);
}

JNIEXPORT void JNICALL native_thread_start(JNIEnv *env,jobject jthiz)
{
    LOGI("native_thread_start");
    gIsThreadStop = 0;

    pthread_t id;
    if(pthread_create(&id,NULL,native_thread_exec,NULL)!=0)
    {
        LOGI("native thread create fail");
        return;
    }

    LOGI("native thread creat success");
}

JNIEXPORT void JNICALL native_thread_stop(JNIEnv *env,jobject jthiz)
{
    gIsThreadStop = 1;
    LOGI("native_thread_stop");
}


static JNINativeMethod methods[] = {
        {"nativeInit","()V",(void*)native_init},
        {"nativeThreadStart","()V",(void*)native_thread_start},
        {"nativeThreadStop","()V",(void*)native_thread_stop}
};

jint JNI_OnLoad(JavaVM *vm, void *reserve)
{
    LOGI("JNI_OnLoad");
    JNIEnv *env;
    if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK)
    {
        return -1;
    }

    jclass jthiz = env->FindClass(classPath);

    if(env->RegisterNatives(jthiz,methods,sizeof(methods)/sizeof(methods[0]))<0)
    {
        return -1;
    }
    return JNI_VERSION_1_4;
}

 

 

 

   由上述代碼可以看到,JNI層通過pthread庫完成了線程的建立,需要特別注意的是,JNI層的線程中,必須通過全域的JavaVM來擷取到環境變數,也必須通過全域的jobject擷取java類對象,從而找到java端的函數,進行回調。

Android開發實踐:JNI層線程回調Java函數樣本

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.