概述
NDK(Native Development Kit )一個工具集,它允許在Android開發中使用C/C++代碼來使用物理設備的一些組件,比如傳感器、輸入設備等。
下載NDK和工具
- NDK:NDK Downloads
- CMake:一個外部的構建工具,與Gradle建立自己的本地庫。 你不需要這個組件,如果你只打算使用ndk-build。
- LLDB:用於調試本地代碼的調試器。
PS:這些工具都可以使用SDK Manager下載。
當前博文所用例子的環境如下所示:
名稱 | 版本號 |
---|---|
Android Studio | 2.1 |
JDK | 1.8.0_65 |
NDK | 12.1.2977051 |
compileSdkVersion | 23 |
buildToolsVersion | 23.0.2 |
minSdkVersion | 23 |
targetSdkVersion | 23 |
PS:NDK如果在第三方平臺下載,解壓後需要配置環境變量—新建變量ANDROID_NDK,變量值爲NDK解壓路徑,並把ANDROID_NDK追加到path中。
創建第一個NDK應用
1. 創建一個基本的項目
2. 配置NDK環境
在文件local.properties中配置ndk路徑(追加即可)
ndk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\sdk\\ndk-bundle
PS:如果在安裝AS時使用默認路徑,並且ndk使用AS集成的SDK Manager軟件下載,則上面的路徑是通用的,否則需要自行配置。
3. 創建一個Jni類
在Module app中創建一個普通類JniTest.java
,並定義一個使用native
修飾的方法getStringFromNative
。結果如下圖所示:
4. Make(構建)Module app生成字節碼(*.class)文件
接下來是構建app項目,構建的方式可以使用Make,也可以使用build,下面以Make爲例子。操作步驟很簡單,首選選中Module app,接着點擊菜單欄的**Make Module ‘app’**即可。圖片說明如下:
如果順利在路徑:app\build\intermediates\classes\debug\com\sandwich\jelly\myapplication下會生成字節碼文件JniTest.class
PS:構建是爲了把項目中所有的源文件(.java)編譯成爲字節碼文件(.class)的過程。所以,實際上可以使用javac
命令去生成。
5. 生成頭文件(*.h)
- 首先打開工具欄的Terminal工具,使用
cd
命令定位到Moduel app的main目錄,如下圖:
- 接着在Terminal工具輸入下面命令:
javah -d jni -classpath ../../build/intermediates/classes/debug com.sandwich.jelly.myapplication.JniTest
javah 執行javah命令生成頭文件(*.h)
-d jni 在當前目錄創建一個文件,文件名稱是jni
-classpath xxx/debug 指定要生成頭文件(*.h)的字節碼文件路徑(*class)
com.sandwich.jelly.myapplication.JniTest
包名(com.sandwich.jelly.myapplication)+字節碼名稱(JniTest)
順利情況下,在路徑:*app/src/main/*下會生成一個文件夾jni,文件夾下生成一個文件com_sandwich_jelly_myapplication_JniTest.h
,該文件會有一個未實現的方法,方法名稱爲JNICALL Java_com_sandwich_jelly_myapplication_JniTest_getStringFromNative
,該方法對應的就是JniTest.java類對應的getStringFromNative方法。
6. 創建JniTest.c文件
第5步中說到了一個方法JNICALL Java_com_sandwich_jelly_myapplication_JniTest_getStringFromNative
,這相當於是java的抽象方法,它只聲明但是沒有任何實現,一般情況下需要創建一個c或cpp文件去實現相應的方法。
- 首先創建一個文件JniTest.c
- 編輯JniTest.c,導入頭文件com_sandwich_jelly_myapplication_JniTest.h
- 實現頭文件的抽象方法
PS:當Android開發中調用JniTest類中的getStringFromNative方法時,它對應的實現是在JNICALL Java_com_sandwich_jelly_myapplication_JniTest_getStringFromNative
方法中。所以實現了java代碼和C層代碼的通信。
7、準備就緒,開始構建.so文件。
方法與第4步的方法相同,使用Make工具。
構建完成後在路徑:app\build\intermediates\ndk\debug\lib下會生成符合各個系統的so庫。
PS:如果構建出現下面錯誤:
在gradle.properties文件中追加下面代碼即可:
android.useDeprecatedNdk=true
8、使用so庫,顯示Hello AS!
- 使用so庫。在JniTest.java中添加代碼
static {
System.loadLibrary("app");
}
添加完代碼後,如下圖:
PS:System.loadLibrary("app");
中的app表示的是庫名稱,前面的lib不需要填寫。
- 編寫一個MainActivity.java,並使用JniTest.java中的getStringFromNative方法。如下圖:
9、運行Module app
運行成功,結果如下圖: