android 中為什么實(shí)用NDK,網(wǎng)上一搜一大堆,在這原因不在贅述。
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序定制開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了昭平免費(fèi)建站歡迎大家使用!
在Android SDK首次發(fā)布時(shí),Google就宣稱其虛擬機(jī)Dalvik是支持JNI編程方式的;也就是第三方的應(yīng)用是可以調(diào)用自己公司的或者是其他C、C++動(dòng)態(tài)庫。
搭建平臺(tái):1.我這用的是MacBook,系統(tǒng)是OS X 10.11.5;
2.Android Studio 2.1.2
3.JDK1.8.0_77 x86_64
首先搭建NDK開發(fā)環(huán)境。啟動(dòng)Android Studio,在Android studio中,屬性—>Appearance & Behaveor —> System Settings —> Android SDK選項(xiàng)(注意:windows在使用NDKr8版本之上的NDK編譯版本,是不需要cygwin來模擬linux,進(jìn)行交叉編譯的)。如下圖所示:
打開右邊的SDK Tools下邊的選項(xiàng)欄有一個(gè)NDK的選項(xiàng),打上對(duì)勾,點(diǎn)擊Apply按鈕,接著會(huì)出現(xiàn)下載NDK文件的對(duì)話框,點(diǎn)擊accept—>OK,會(huì)下載NDK文件,通常NDK會(huì)安裝到SDK的目錄下面。
下載安裝完成之后配置NDK環(huán)境變量:
1.Windows 上是在計(jì)算機(jī)—》屬性—》高級(jí)—》環(huán)境變量,在path上追加NDK的安裝目錄。
2.linux或者是MAC是在家目錄的.bash_profile中,添加環(huán)境變量,例如export NDK_HOME=/Users/XXX/Android/SDK/ndk-bundle export PATH=$PATH:$SDK_HOME。
OK.測(cè)試NDK是否安裝配置成功,打開終端,輸入ndk-build -version.回車
顯示
表示安裝成功。
1.創(chuàng)建一個(gè)Android項(xiàng)目來測(cè)試一個(gè)Android的使用方式,在這命名為JNIDemo;創(chuàng)建項(xiàng)目的過程不再贅述。
2.在Andorid視圖中建立jni文件夾,右鍵—>New—>Folder—>JNI Folder,確定。會(huì)創(chuàng)建一個(gè)jni目錄。這個(gè)目錄就是存放c源碼的文件。(jni目錄的創(chuàng)建,也可以在project視圖中在main文件中創(chuàng)建一個(gè)jni目錄。如果在Android視圖中創(chuàng)建JNI Folder,再切換到Project視圖,你會(huì)發(fā)現(xiàn),main目錄下有一個(gè)jni目錄,兩個(gè)本質(zhì)上是一致的)。
3.配置需要CUP編譯成的架構(gòu)庫(.so文件)。
defaultConfig { applicationId"com.zzh.jni" minSdkVersion14 targetSdkVersion23 versionCode1 versionName"1.0" ndk{ moduleName"zzhJni”//c/c++編譯成的庫文件名稱 abiFilters"armeabi","armeabi-v7a","arm64-v8a","x86","x86_64"http://需要適配哪幾種類型的CPU架構(gòu)。 } } |
4.在gradle.properties(Project Properties)中添加android.useDeprecatedNdk=true;
在local.properties中添加ndk.dir=/Users/XXX/Android/SDK/ndk-bundle(自己安裝NDK的路徑)
5.新建一個(gè)jni調(diào)用類NdkUtils寫一個(gè)native方法。在Java中,Java調(diào)用c/c++中的程序,需要使用到native關(guān)鍵字表示Java中調(diào)用C/C++中的方法。
package zzh; public class NdkUtils { public static native String getMapHeader(); }
6.點(diǎn)擊Build—>Make Project,編譯文件,編譯后
在終端,進(jìn)入到debug目錄,運(yùn)行javah -jni zzh.NdkUtils回車,生成c的頭文件,頭文件的命名為“包名_類名(包名之間的“.”使用“_”分割開的)”。將此文件復(fù)制到j(luò)ni目錄中,打開可以看到一下內(nèi)容
/* DO NOT EDIT THIS FILE - it is machine generated */ #include/* Header for class zzh_NdkUtils */ #ifndef _Included_zzh_NdkUtils #define _Included_zzh_NdkUtils #ifdef __cplusplus extern "C" { #endif /* * Class: zzh_NdkUtils * Method: getDeviceIdFromNdk * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_zzh_NdkUtils_getMapHeader (JNIEnv *env, jobject obj); #ifdef __cplusplus } #endif #endif
· JNIEXPORT jstring JNICALL Java_zzh_NdkUtils_getMapHeader(JNIEnv *env, jobject obj); 就是我們之前所用native在NdkUtils.java聲明的方法。這個(gè)只是C/C++的一個(gè).h文件,方法的具體實(shí)現(xiàn),還要一個(gè).c。這個(gè).c文件,自己創(chuàng)建就好。
方法實(shí)現(xiàn)如下
#include "zzh_NdkUtils.h" JNIEXPORT jstring JNICALL Java_zzh_NdkUtils_getMapHeader (JNIEnv *env, jobject obj){ return (*env) -> NewStringUTF(env, "string from c"); }
7.至此C語言,就寫好了,怎么讓c/c++生成庫文件呢,先點(diǎn)擊Build-clean Project(先clean是因?yàn)楸苊庠诰幾g的時(shí)候產(chǎn)生沖突),再make Project,在6步驟的圖片中classes同級(jí)目錄下有ndk目錄,此目錄下有生成好的庫文件。
復(fù)制arm*、x86*到j(luò)niLibs目錄中,就像我們?cè)谧鲰?xiàng)目時(shí),將第三方的.so文件放入到j(luò)niLibs目錄一樣。Android.mk復(fù)制到j(luò)ni文件中。
8.最后一步,調(diào)用生成的庫文件。
在NdkUtils.java中,添加
static{
System.loadLibrary(“zzhJni"); //這一行,表示要加載C語言庫,zzhJni就是編譯成的c庫文件,也就是在第三步中build.gradle中配置的moduleName 的名字
}
這樣就可以在Java代碼中調(diào)用c/c++方法了。
示例:
在MainActivity.java中調(diào)用:
public class MainActivity extends Activity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.textView); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { String str = "" + NdkUtils.getMapHeader(); mTextView.setText(str); } catch (Exception ex) { ex.printStackTrace(); } finally { } } }); } }
布局文件:
運(yùn)行截圖:
文筆有限,寫的不好,敬請(qǐng)?jiān)?,如有錯(cuò)誤,敬請(qǐng)指正