最近因爲項目的須要,使用到了Android的NDK技術,對項目核心算法跨平臺的移植。簡答而言,就是使用C對原來的算法進行了改進,並集成到原來的app項目裏。 html
從前的項目一直沒有使用NDK進行開發的機會,於是一直仰慕那些技術大牛們關於NDK以及C/C++開發而寫的文章,以爲很深奧,於是一直蠢蠢欲動。 java
其實NDK的開發並不複雜,就入門而言甚至能夠說是easy job,以爲它難是難於C/C++代碼的編寫與調試。這個是我最近從事NDK開發的一點感覺! android
首先,咱們要弄懂幾個概念,何爲NDK,它和SDK以及JNI有什麼關係?請前看下圖: 算法
JNI是Java衆多開發技術中的一門,意在利用本地代碼,爲Java程序提供更高效,更靈活的拓展。應用場景包括:對運行效率敏感的算法實現、跨平臺應用移植、調用系統的底層驅動、調用硬件等。儘管Java一向以其良好的跨平臺性而著稱,但真正的跨平臺之王,應該是C/C++,由於當前世上90%的系統都是基於C/C++編寫的。Java的跨平臺,是以犧牲效率換來對多種平臺的兼容性,於是JNI能夠說是Java短板的補充!舉一例子說明,當前流行的移動操做系統Android,一直被說系統操做的流暢性不如IOS,緣由在於Android的App是基於Java開發的,IOS的是基於Object-C開發的,區別在於一樣的操做,在IOS上一條指令完成,在Android上則須要多大三條指令才能完成(數據來自於網絡,不必定準確)!因而在Android JellyBean版本中,Google爲其引入ProjectButter(黃油計劃),在應用層大量使用了本地庫,並優化了系統的架構,以提高Android系統總體的操做反應! windows
咔咔,JNI的介紹就先說到這裏,總之,JNI是一門技術,是Java Code和C/C++ Code聯繫的橋樑! 網絡
一、編寫Java Code,以下面的例子: 架構
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(getApplicationContext(), sayHellow(), Toast.LENGTH_LONG).show(); } public native String sayHellow(); //調用本地方法 static { System.loadLibrary("Scgps_Client"); //加載本地共享庫 } }
二、編寫C/C++ Code,以下面的例子: oracle
#include #include JNIEXPORT jstring JNICALL Java_com_scgps_client_MainActivity_sayHellow(JNIEnv* env, jobject thiz) { const char * ret = "Hellow Form Ndk"; return (*env)->NewStringUTF(env, ret); }三、編譯 C/C++ Code,成功並獲得本地共享庫
本地共享庫是Linux下的叫法,文件擴展名是.so,windows下叫動態連接庫,文件擴展名是.dll。前面說到C/C++纔是跨平臺之王,這就是其中的道理,面對不一樣的平臺,編譯不一樣的結果。相對於Java的一次編譯處處運行的跨平臺性犧牲運行效率,C/C++的跨平臺性則是犧牲編譯時間以及編譯的難度。這裏的編譯難度是指爲適應不一樣平臺而作的編譯過程的調整,這個活的難度可大可小,還不必定成功,視乎平臺的兼容性以及支持。說到這裏,不免會有人噴了:說什麼跨平臺性,這麼複雜還不穩定!的確C/C++的跨平臺性是有侷限性的,可是縱觀當前的各類平臺和系統,有哪家是不支持C/C++本地開發的?只是各自提供的底層API和編譯條件不一樣而已,只須要調整一下C/C++的編譯代碼,經過編譯便可運行,難道也不是一件美事? app
四、編譯並打包Java ide
把本地共享庫放置到Java項目的指定目錄,通常是libs文件件,Android的項目是libs/armeabi(armeabi是對應的平臺,後面會詳講),而後編譯Java的代碼便可運行!
NDK是Google爲Android進行本地開發而放出的一個本地開發工具,包括Android的Native API、公共庫以及編譯工具,注意,NDK須要Android 1.5版本以上的支持哦。
按照上圖的解說,NDK處在開發流程的編譯環節,對,簡單來講,NDK是JNI開發的一個擴展工具包!針對Android平臺,其支持的設備型號繁多,單單就設備的核心CPU而言,都有三大類:ARM、x86和MIPS,何況ARM又分爲ARMv5和ARMv7等等,爲什麼Android又能適配如此之多的設備?接着JNI開發流程的話,利用NDK,咱們能夠針對不一樣的手機設備,編譯出對應可運行的本地共享庫了,至於如何使用NDK進行編譯、開發,咱們留做下次再進行探討。
SDK是Google提供的Android標準開發工具包,裏面包含了完整的API文檔,各Android版本的開發庫,Android的虛擬機以及Android的打包工具等。衆所周知,Android的應用開發語言是Java,App的運行時是Delvik Runtime,屬於JVM的改良版本,官方說Delvik VM更適用於移動設備。通常而言,因爲Google的SDK提供了強大又完善的API,開發通常需求的應用,SDK足矣。然而前面已經說過,Java的運行效率引起了很多問題,於是纔有了JNI技術的存在,那SDK和NDK的關係是怎樣的呢?見下圖解說,能夠說,NDK是SDK的一個補充。
這個開發流程大體與JNI的開發流程差很少,下面我再詳細說明一下每一個環節:
SDK開發,編寫Java代碼,調用各類Android的API實現功能,編寫含有native關鍵字的代碼開始JNI;
JNI開發,按照 JNI編碼規範,編寫與Java交互的本地代碼,通常就是數據類型的轉換,把C/C++的數據類轉換成Java能識別的,或反過來。也由於這樣子,我認爲JNI其實就是Adapter,做爲數據轉換層而存在,具體JNI的通常操做,我以後再分享;
C/C++開發,編碼實現業務邏輯,或調用NDK提供的本地API或庫,完成Android平臺上特定功能的開發、封裝;
NDK編譯,編寫.mk文件,編譯調試,最後修改.mk文件,針對特定的平臺(ARM/x86)作編譯結果的優化;
最後就是SDK編譯、打包,上真機調試了...
本篇博客的內容均是我的在開發工做中的一些感悟及心得,鑑於本人認知有限,若有不實,請留言告知,望見諒。
本文由zhiweiofli編輯發佈,轉載請註明出處,謝謝。