Android NDK官方介紹html
The Android NDK is a toolset that lets you implement parts of your app using native-code languages such as C and C++. For certain types of apps, this can help you reuse code libraries written in those languages.java
實如今你的Android應用中調用C程序實現一些功能。那爲何要在Java開發中使用C語言呢?android
代碼的保護。因爲apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大。git
能夠方便地使用現存的開源庫。大部分現存的開源庫都是用C/C++代碼編寫的。github
提升程序的執行效率。將要求高性能的應用邏輯使用C開發,從而提升應用程序的執行效率。服務器
便於移植。用C/C++寫得庫能夠方便在其餘的嵌入式平臺上再次使用。
PS:資料來源app
雖然關於NDK開發的學習資料很少,Google官方並不少關於NDK開發文檔,但居然NDK開發包那必然有它的意義。因此咱們有必要對NDK開發有個初步認識。這節主要搭建NDK開發環境並在應用中調用native函數方法。函數
從ndk-7後,谷歌已經改良了ndk的操做,不需用使用cygwin來交叉編譯,因此這裏就再也不講cygwin的配置。所搭建的開發環境是Android Studio性能
1.在官方下載Android NDK開發包 下載地址目前最新的版本爲r12b學習
2.添加java系統環境變量(若是Android Studio的terminal中沒法使用javah指令的時候須要作此步操做)
變量 | 值 |
---|---|
CLASSPATH | .;%JAVA_HOME%lib; |
JAVA_HOME | X:XXJavajdk1.8.0_05 |
PATH | %JAVA_HOME%bin; |
3.新建Android工程,添加項目構建NDK本地路徑
4.local.propertices中添加ndk.dir=c:\Android-ndk
5.gradle.properties文件中添加android.useDeprecatedNdk=true
1.新建類JniFunction,實現兩個native方法
public class JniFunction { static public native String getJniString();//獲取字符串 static public native int addNumber(int a,int b);//獲取兩個整數相加值 }
2.rebuild Project,在工程目錄下app/intermediates/classes/debug下查找到JniFunction.class
3.在main目錄下建立一個jni文件夾
4.打開Android Studio的terminal,使用cd定位在Android工程的app目錄下輸入
javah -d jni -classpath ..\..\build\intermediates\classes\debug com.xxxxxxx.xxx.JniFunction //切記debug和com之間有空格
5.在jni文件夾中就生成了com_learnncode_learnndk_JniFunction.h的頭文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_learnncode_learnndk_JniFunction */ #ifndef _Included_com_learnncode_learnndk_JniFunction #define _Included_com_learnncode_learnndk_JniFunction #ifdef __cplusplus extern "C" { #endif /* * Class: com_learnncode_learnndk_JniFunction * Method: getJniString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_learnncode_learnndk_JniFunction_getJniString (JNIEnv *, jclass); /* * Class: com_learnncode_learnndk_JniFunction * Method: addNumber * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_learnncode_learnndk_JniFunction_addNumber (JNIEnv *, jclass, jint, jint); #ifdef __cplusplus } #endif #endif
6.在jni文件夾下新建C/C++ Source File,複製h頭文件中定義的函數實現函數內容。須要注意的是選擇新建.c文件而不是.cpp,另外記得多添加一個無用的c文件,否則編譯可能會出錯。
#include "com_learnncode_learnndk_JniFunction.h" /* * Class: com_learnncode_learnndk_JniFunction * Method: getJniString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_learnncode_learnndk_JniFunction_getJniString (JNIEnv * env, jclass obj){ return (*env)->NewStringUTF(env,"Hello Android NDK"); } /* * Class: com_learnncode_learnndk_JniFunction * Method: addNumber * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_learnncode_learnndk_JniFunction_addNumber (JNIEnv * env, jclass obj, jint a, jint b){ return a + b; }
7.在app build.gradle添加ndk配置
defaultConfig { applicationId "com.learnncode.learnndk" minSdkVersion 14 targetSdkVersion 24 versionCode 1 versionName "1.0" ndk{ moduleName "JniFunction" //設置庫(so)文件名稱 } }
8.在jni調用的地方添加如下內容
static { System.loadLibrary("JniFunction"); } //JniFunction就是build.gradle中NDK的文件名
1.so文件的生成
在app build.gradle中設置ndk生成so文件庫文件名
ndk{ moduleName "JniFunction" //設置庫(so)文件名稱 abiFilters "armeabi","armeabi-v7a","x86" }
編譯項目後在項目目錄下ndk文件中就能看到生成的so文件
ABI:指應用基於哪一種指令集來進行編譯,ABI總共有四種,分別是armeabi、armeabi-v7a、mips、x86,它們都是表示cpu的類型。
安卓支持三類處理器(CPU):ARM、Intel和MIPS。ARM無疑被使用得最爲普遍。Intel由於普及於臺式機和服務器而被人們所熟知,然而對移動行業影響力相對較小。MIPS在32位和64位嵌入式領域中歷史悠久,得到了很多的成功,可目前Android的採用率在三者中最低。
2.Android studio2.2環境下目錄變化
更新了Android Studio以後發現加載目錄發現了變化,原來的Jni文件放置在了單獨的文件目錄下
Project
Android
Android項目調用.so文件方法:在src/main/目錄下新建jniLibs文件夾把ndk abiFilters生成的so文件拷貝在此目錄下,再在build.gradle defultConfig中配置jniLibs路徑,看過其餘人寫的默認寫的是libs好像也是可運行的,這裏我仍是填上正式新建時的路徑
sourceSets.main{ jniLibs.srcDirs "src/main/jniLibs" }
NDK開發環境的搭建算不上特別難,就是麻煩了些。以前看別人的教程說NDK r10b版本是比較穩定的,我使用的是r12b也能編譯成功,目前看來仍是可使用的。這節先爲NDK開發開一個頭,其中也沒詳細講解關於NDK開發的語法等內容。學習NDK的道路仍是任重而道遠啊。附上google官方的NDK開發Demo實例
本節Demo項目地址