Android-NDK-r4b學習之概述

來源:互聯網
上載者:User

      前兩天被人問起是否瞭解Android下的NDK開發,當時懵了,之前確實聽說過這麼個工具集,但具體做什麼用,怎麼用,為什麼用都一無所知。於是決定好好學習下。NDK目前最新版本是r4b,本人學習的資料主要是NDK-r4b內建的的docs/目錄下的.txt檔案。

      Android NDK是個工具集,利用NDK可以實現在java應用中嵌入用C/C++編寫的本地代碼編譯後的二進位碼,二進位碼以動態庫的形式存在。不過,NDK只能用於1.5版本及其以後的系統。

      開發NDK的目標有三個
:一是在應用中調用通過JNI實現的本地程式(C和C++編寫);二是對SDK起到輔助作用;三是提供一些工具和平台說明檔案。

      實現NDK第一個目標有下面幾件事要做:

      1、在應用程式中,通常是JAVA編寫的Class,用"native"關鍵字聲明需要調用的本地程式。這裡將C和C++編寫的程式稱為本地程式是相對於運行於虛擬機器(VM)上的應用而言的。如:    native byte[]  loadFile(String  filePath);

      2、提供包含1中聲明的本地程式的動態庫,並將其打包到應用程式的.apk中。動態庫的命名需要遵循UNIX的約定,採用lib<something>.so,包含JNI的進入點。如:libFileLoader.so

      3、在應用程式中顯示的載入2提供的動態庫。通常在應用程式的起始位置添加如下代碼:

          static {

                  System.loadLibrary("FileLoader");

         }

注意:這裡引用動態庫時,不需要lib首碼和.so尾碼。

      NDK對SDK的輔助作用體現在一下幾點:

            1、產生與JNI標準相容的動態庫,可以運行在ARM CPU+1.5版本及其以後的平台上。

            2、編譯產生並拷貝動態庫到應用工程的合適位置,然後自動將其添加到.apk中。運行ndk-build,會自動完成編譯和打包的工作。

            3、目前沒有提供本地代碼調試工具,在以後的版本中考慮添加通過遠程GDB串連調試的工具

     NDK提供了一套工具和檔案:

            1、一套交叉編譯工具,包括:編譯器,連接器等等,可用來在Linux, OS X and Windows (通過 Cygwin)平台上產生ARM二進位檔案。

            2、一組與Android平台支援的穩定的本地API列表相對應的系統標頭檔,在檔案docs/STABLE-APIS.TXT中有說明。這裡的穩定API是指那些能夠保證被當前及其之後版本都支援的API,因為,在Android的系統鏡像中,大部分本地系統庫並非一成不變的,可能變動很大甚至被刪除在當前系統的後續版本中。

            3、一個系統構建工具(build system),允許開發人員編寫短小的構建檔案(android.mk/application.mk)來描述需要編譯哪些源檔案、怎樣編譯。NDK將在其後續版本中繼續更新系統構建工具集、平台系統介面,而無須開發人員修改他們的構建檔案。

            另外,NDK下還提供了一套Sample,可以通過閱讀那裡面的代碼更直觀的感受NDK的開發精髓。

作為NDK的使用者,除了掌握NDK能做什麼之外,還有注意NDK作為一種工具和輔助手段,必有其局限性,如同高懸於頂上的德謨克利斯之劍
,因此,開發人員在使用時,也需要掌握一些使用規則:

            1、不要用NDK去開發通用的運行在Android裝置上的程式。尤其要強的是應用程式以及系統事件的處理常式應堅持用JAVA語言來編寫,儘管利用NDK的本地編碼方式也能編寫複雜的應用,但不推薦這樣做。根據本人的開發經驗來看,這樣做的代價實在太大,可能用JAVA幾行的代碼,用NDK的本地代碼要幾百行,這跟JNI的那套機制有關,需要通過一系列的手段在C/C++代碼中去回調JAVA代碼。

            2、對JNI介面標準有良好的理解,因為該標準下要求開發人員採取一些特殊的做法,而這些做法不是典型的本地代碼的通行操作,如:

                 1}、本地代碼無法直接存取VM(Virtual Machine)上對象的內容。

                 2}、當本地代碼想在JNI調用中處理VM上的對象,自己就必須顯示的進行引用管理。JNI標準支援LocalRef、GlobalRef以及WeakGlobalRef三類引用,需要本地代碼對這些引用進行適當的處理,否則會帶來記憶體泄露甚至程式崩潰的惡果。

            3、NDK之提供了Android平台支援的數量非常有限的本地API的集的系統標頭檔和庫檔案,而典型的Android系統鏡像包含了大量的其它本地動態庫,這種做法的目的是考慮到NDK中未包含的庫在Android後續版本中可能被大規模修改。因此,實際應用中,應用程式不應該依賴那些非NDK的庫。

 

      NDK開發步驟粗略概括為以下幾步:

            1、將本地代碼放在路徑:$PROJECT/jni/...,這裡的$PROJECT是指當前JAVA應用工程的頂級目錄。

            2、為本地代碼編寫Android.mk檔案,共置於$PROJECT/jni/...目錄下,該檔案是本地代碼的構建描述檔案

            3、可選項:編寫Application.mk,同樣置於$PROJECT/jni/...目錄下,該檔案更詳細的描述了工程的構建過程。儘管不是必須的,如果開發人員這麼做的話,就可以指定多個CPU平台,修改編譯和串連標誌。詳情見docs/APPLICATION-MK.TXT

            4、在$PROJECT/jni目錄下執行$NDK/ndk-build命令,完成本地代碼的構建。如果已經將NDK的安裝路徑$NDK添加到系統標準路徑中了,則可直接運行ndk-build。如果構建成功的話,產生的動態庫會被自動拷貝到當前工程目錄下的lib檔案夾中,並被添加到.apk中。

     NDK開發步驟的詳細描述如下:

            1、進行NDK開發前,首先要進行NDK的配置。NDK-r4b之前版本的配置是直接運行build/host-setup.sh來完成的。而在該版本中已經將這過程移除,因此,在build目下已經沒有host-setup.sh指令碼了。真要將下載的NDK開發包直接解壓即可,不過,為了方便使用,最好將解壓目錄添加到系統的標準路徑中,這樣就可以在系統中的任何路徑下直接使用NDK命令了。

            2、C/C++源檔案的放置:直接至於目錄$PROJECT/jni/下,如果jni目錄不存在,建立之。jni下檔案的組織是很自由的,目錄的名稱和結構不會影響應用程式產生的包,因此,開發人員不需要像應用程式套件組合裡那樣進行檔案命令。C++檔案預設的副檔名是.cpp,同時,也能處理其它類型的副檔名,詳情見docs/ANDROID-MK.TXT。當然,通過調整Android.mk檔案也可以將C/C++源檔案放在其它地方。

            3、Android.mk指令碼編寫:這是個小型的用於NDK開發的指令碼,描述NDK中本地代碼的構建。NDK將本地代碼編譯成一個或多個模組,這些模組可能是動態庫或靜態庫。值得注意的是一個Android.mk可以定義多個模組的構建,也可以為每個模組單獨編寫一個Android.mk。如果是單個Android.mk對應多模組的話,Android.mk可能會被構建系統多次讀取,因此,不要做某些變數在Android.mk中未被定義的假設。預設將Android.mk放在$PROJECT/jni目錄下,如果想將其放在子目錄下,就要在頂層目錄的Android.mk中顯示的指出來,如: include $(call all-subdir-makefiles),這樣是告訴構建系統去遍曆當前構建檔案所在路徑子目錄下的所有Android.mk。

            4、Application.mk的編寫(可選):相對於描述模組構建的Android.mk而言,該檔案是用來對應用程式本身構建進行描述的,描述內容通常包括:應用所需的所有模組的列表、目標CPU架構以及編譯版本(Debug 或Release),c/c++編譯標誌及其它適用於所有模組的編譯選項等可選內容。該檔案是可選的,NDK預設的會提供一個簡單的Android.mk,裡面只是列舉所有需要構建的模組,CPU架構預設的是ABI(armeabi)。Application.mk的使用有兩種方式:

                 1}、直接放到$PROJECT/jni目錄下,ndk-build指令碼會自動讀取

                 2)、將Application.mk放到$NDK/apps/<name>/目錄下,$NDK是NDK的安裝目錄,在該目錄下通過命令:make APP=<name> 來執行該指令碼。這種方式是r4b版本之前的NDK常用的方式,為了保持相容,r4b也支援這種用法,但不建議這麼用,還是建議的一種方式,相對來說簡單,不需要關心NDK的安裝路徑。

            5、啟動NDK構建系統,兩種方法:

                 1)、使用ndk-build命令:ndk-build指令碼位於$NDK下

                 2)、使用$NDK/apps/<name>/Application.mk。這種方式在r4b以前的版本中使用,雖然在r4b中也可以用,不過不推薦。因此,使用此法比較繁瑣,需經以下步驟:

                          首先,在NDK的安裝目錄下建立子目錄$NDK/apps/<name>/,name用來向NDK構建系統描述應用,不允許帶有空格

                          其次,編寫Application.mk,共置於$NDK/apps/<name>/下,在Application.mk中需要定義APP_PROJECT_PATH,用來指向工程目錄$PROJECT

                          最後,切換到$NDK下,執行命令:make APP=<name>

 

      NDK的調試支援:NDK中提供了ndk-gdb指令碼,能很方比的啟動應用程式中的本地偵錯工作階段。本地調試僅適用於Android2.2及其之後的版本,只要應用程式開啟debuggable即可,不需要root許可權以及其它特殊存取權限。更詳細的資訊見:docs/NDK-GDB.TXT。不過,本地調試的啟動可以簡單歸納為以下幾步:

            1、確定應用的debuggable已經啟動,在AndroidManifest.xml中設定android:debuggable=true 即可;

            2、利用ndk-build構建應用程式,並將其安裝到裝置/模擬器上;

            3、在裝置/模擬器上啟動應用;

            4、在應用工程目錄$PROJECT下運行ndk-gdb

這樣就會出現gdb命令列,參照gdb使用手冊上的命令就可以進行調試了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.