1. 程式人生 > >AndroidStudio3.0中JNI開發

AndroidStudio3.0中JNI開發

1.什麼是JNI?

   JNI 是java native interface  的縮寫,如果想實現JAVA呼叫C、C++ ,那麼就需要利用JNI來實現,JNI可以使java和c、c++ 相互呼叫, JNI可以看做是翻譯,其實就是一套協議。

 

2.為什麼要用JNI?

          驅動程式一般都是用C寫的,如果JAVA想操作硬體那麼就需要去跟C去互動,如果想利用android 軟體來控制硬體,比如在手機中點選一個按鈕就可以控制電燈的開啟和關閉,比如點選手機中的按鈕就可以控制小區門禁的開啟和關閉 ,比如如果想實現人臉識別的功能,就可以利用java來呼叫jni,然後通過jni來呼叫OpenCV實現人臉識別的功能.

 

3.怎麼使用JNI?

要用JNI,首先要學c、c++的基礎
NDK 是native develop kit的縮寫,     DNK是谷歌在Androud下給開發JNI的一套工具

3.0 給當前的專案新增NDK支援

 3.1、宣告一個本地函式:

  /**
     * JNI開發的步驟
     * 1、宣告本地方法,使用native關鍵字,該本地方法不用實現
     * @return
     */
    public native String helloFromC();

3.2、在專案的main資料夾下建立jni檔案下,比建立一個.c檔案

3.3、建立一個本地函式,比實現該函式

/*
建立本地函式
在C中用jstring來表示JAVA中的String
C本地函式的命名規則為:

Java_呼叫C本地函式的的使用者包名_使用者類名_呼叫本地函式的函式名(JNIEnv* env,jobject thiz)
Java_com_casic_jni_MainActivity_helloFromC(JNIEnv* env,jobiect thiz)


JNIEnv* env 是一個指標, 它是結構體JNINativeInterface 的二級指標
JNIEna 是結構體JNINativeInterface的一級指標
實現將 JNIEnv* env轉換成JNINativeInterface的一級指標: (*env)
->是C中的間接運算子


jobiect 即相當於JAVA中的object  ,它是呼叫本地函式的java物件,當前的thiz就是MainActivity這個物件


(JNIEnv* env,jobiect thiz) 這兩個引數是固定的,就算呼叫C的本地函式時不用傳遞任何引數,那麼這兩個引數也是必須要有有的。如果需要傳遞引數,那麼在後面新增即可
*/
jstring Java_com_casic_jnitestthree_MainActivity_helloFromC(JNIEnv* env,jobject thiz){

    /*
    實現當呼叫本地函式時返回一個字串回去
    */
    char* str = "hello from c!";
    //通過jni.h中的NewStringUTF(env,cstr) 函式實現將char*資料型別轉換為jstring資料型別
     return (*env)->NewStringUTF(env,str);
}

 

3.4、在jni目錄下建立一個Android.mk檔案,並在其中加入如下程式碼:

LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE    := hello
    LOCAL_SRC_FILES := hello.c

    include $(BUILD_SHARED_LIBRARY)

3.5、進入到該專案的根目錄下,通過ndk-nuild命令對其c檔案進行編譯,如果編譯成功就會在生成如下檔案

3.6、在main目錄下建立一個jniLibs的檔案下,並將libs檔案下的所有檔案都拷貝到該目錄中

3.7、載入so檔案

   System.loadLibrary("hello");

 

3.8、呼叫最開始宣告的本地函式

             /*
                * 6、呼叫本地函式
                * */
                String s = helloFromC();
                Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();

 

3.9、在gradle.properties檔案中的預設新增如下程式碼:

Android.useDeprecatedNdk=true 

3.10、在app的build.gradle檔案中新增如下程式碼:

        ndk{
            moduleName "hello"
        }

        sourceSets.main{
            jniLibs.srcDirs = ['src/main/jniLibs'];
        }
        sourceSets {
            main {
                jni.srcDirs = []
            }
        }

 

效果圖:

原始碼下載