NDK-JNI實戰教程(一) 在Android Studio運行第一個NDK程序
PS一句:最終還是選擇CSDN來整理發表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支持MarkDown語法了,牛逼啊!
NDK開發,其實是為了項目需要調用底層的一些C/C++的一些東西;另外就是為了效率更加高些。如果你在Eclipse+ADT下開發過NDK就能體會到要么是配置NDK還要下載Cygwin,配置Cygwin ,然后需要編譯生成,相當的蛋疼。要么是直接用Eclipse開發,但是前期配置也是一堆;真心蛋疼。但是現在在AS上Eclipse能做到的這邊都OK,這邊有的Eclipse上沒有的,而且Google親生的支持下只會越來越比Eclipse下開發NDK更加牛逼,所以你還不準備上手嗎?
在AS開發NDK JNI也需要配置,不過相當Easy。第一步就是去官方下載個NDK包就可以了,像我的直接放在D盤就行了。關于怎么下載安裝看這里 AD NDK會有介紹。
第二步就是就是直接寫代碼了。哈哈,你沒聽錯,是這樣的,方便吧?至于下載下來的NDK怎么和AS工程關聯,也就是一行配置的問題,后文有說明帶你一步一步體驗。
But,還是要有個but,Android Studio還不是個壯年,尤其在NDK開發中,所以本文只是工具性的演示,實質是教會大家NDK開發。
Let’s Go!!!
在AS中新建一個Project,然后再新建一個class為NdkJniUtils,在內部聲明native方法(jni使用的定義,后面系列教程會細說)。
package io.github.yanbober.ndkapplication; public class NdkJniUtils { public native String getCLanguageString(); }
在工程主文件Activity中寫入如下代碼調運JNI的東西顯示在UI上。
public class MainActivity extends ActionBarActivity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) this.findViewById(R.id.test); NdkJniUtils jni = new NdkJniUtils(); mTextView.setText(jni.getCLanguageString()); } }
然后build project得到其中中間文件,我們關注的是.class文件。編譯OK以后生成的class文件在AS工程的如下目錄:
NDKApplication\app\build\intermediates\classes\debug
然后接下來的步驟就是根據生成的class文件,利用javah生成對應的 .h頭文件。
點開AS的Terminal標簽,默認進入到該項目的app文件夾下。我在windows平臺下輸入如下命令跳轉到class中間文件生成路徑:
xxxxx\app> cd build\intermediates\classes\debug
然后執行如下javah命令生成h文件。
xxxxx\debug> javah -jni io.github.yanbober.ndkapplication.NdkJniUtils
執行完之后你可以在文件夾NDKApplication\app\build\intermediates\classes\debug下看見生成的 .h頭文件為:
io_github_yanbober_ndkapplication_NdkJniUtils.h
其內容為:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class io_github_yanbober_ndkapplication_NdkJniUtils */ #ifndef _Included_io_github_yanbober_ndkapplication_NdkJniUtils #define _Included_io_github_yanbober_ndkapplication_NdkJniUtils #ifdef __cplusplus extern "C" { #endif /* * Class: io_github_yanbober_ndkapplication_NdkJniUtils * Method: getCLanguageString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_io_github_yanbober_ndkapplication_NdkJniUtils_getCLanguageString (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
在工程的main目錄下新建一個名字為jni的目錄,然后將剛才的 .h文件剪切過來。在jni目錄下新建一個c文件,隨意取名,我的叫jnitest.c 。然后編輯代碼如下(后面會解釋啥意思,這里重在工具使用):
#include "io_github_yanbober_ndkapplication_NdkJniUtils.h" /* * Class: io_github_yanbober_ndkapplication_NdkJniUtils * Method: getCLanguageString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_io_github_yanbober_ndkapplication_NdkJniUtils_getCLanguageString (JNIEnv *env, jobject obj){ return (*env)->NewStringUTF(env,"This just a test for Android Studio NDK JNI developer!"); }
接下來在工程的local.properties文件中添加NDK路徑(上面下載好的那個NDK),類似其中的SDK路徑一樣,我的添加后如下:
sdk.dir=D\:\\AndroidStdioSDK\\sdk #add by 工匠若水 ndk.dir=D\:\\AndroidStdioSDK\\android-ndk-r10d-64bit
接下來在app module目錄下的build.gradle中設置庫文件名(生成的so文件名)。找到gradle文件的defaultConfig這項,在里面添加如下內容:
defaultConfig { ...... ndk{ moduleName "YanboberJniLibName" //生成的so名字 abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫。目前可有可無。 } }
現在生成的so庫名字也有了,那就去代碼的NdkJniUtils java文件添加靜態初始化load代碼,添加如下:
static { System.loadLibrary("YanboberJniLibName"); //defaultConfig.ndk.moduleName }
好了,到此AS下NDK JNI開發的代碼編寫和設置就OK了,接下來就是編譯工程運行就可以了。
但是有些電腦好奇怪此時編譯會報錯,妹的,沒轍,后來網上找到答案說這是NDK在Windows下一個bug,當只編譯一個單一文件時出現,解決辦法就是再添加一個空的文件就行了,這個網站有介紹:NDK在Windows的一個bug。不過你要是剛才能順利編譯就沒必要蛋疼這個問題了。
好了,我的編譯運行結果如下:
到此為止簡單的體驗AS下NDK開發的過程就結束了。期待下一篇再續深入。
【工匠若水 http://blog.csdn.net/yanbober】 繼續閱讀《 NDK-JNI實戰教程(二) JNI官方中文資料》 http://blog.csdn.net/yanbober/article/details/45310365