Android NDK開發(fā)(一) ?入門

開始之前

最近學習了一下NDK的開發(fā), 就來分享一下.
對一個新鮮事物, 我們先解決的無非就是三件事情: 是什么?為什么?怎么做?.

NDK簡介

(英語:native development kit嘹履,簡稱NDK)是一種基于原生程序接口的軟件開發(fā)工具锋恬。通過此工具開發(fā)的程序直接以本地語言運行砂碉,而非虛擬機膀懈。因此只有java等基于虛擬機運行的語言的程序才會有原生開發(fā)工具包荣暮。[維基百科]

  1. NDK是一系列工具的集合

NDK提供了一系列的工具颈走,幫助開發(fā)者快速開發(fā)C(或C++)的動態(tài)庫民轴,并能自動將so和java應用一起打包成apk。這些工具對開發(fā)者的幫助是巨大的.

  1. NDK集成了交叉編譯器踊谋,并提供了相應的mk文件隔離CPU蝉仇、平臺、ABI等差異,開發(fā)人員只需要簡單修改mk文件(指出“哪些文件需要編譯”轿衔、“編譯特性要求”等)沉迹,就可以創(chuàng)建出so。

NDK可以自動地將so和Java應用一起打包害驹,極大地減輕了開發(fā)人員的打包工作胚股。

那我們?yōu)槭裁匆褂媚?

  1. 代碼的保護。由于apk的java層代碼很容易被反編譯裙秋,而C/C++庫反匯難度較大。
  2. 可以方便地使用現(xiàn)存的開源庫缨伊。大部分現(xiàn)存的開源庫都是用C/C++代碼編寫的摘刑。
  3. 提高程序的執(zhí)行效率。將要求高性能的應用邏輯使用C開發(fā)刻坊,從而提高應用程序的執(zhí)行效率枷恕。
  4. 便于移植。用C/C++寫得庫可以方便在其他的嵌入式平臺上再次使用谭胚。

上述文字致謝Devin Zhang提供理論支持

是什么和為什么我就先介紹到這兒, 接下來就具體看看如何進行NDK的開發(fā)

開發(fā)前準備

開發(fā)環(huán)境

請大家務必升級到AS 2.2以上版本, 因為這個版本升級了很多內容, 詳情請見 Android Studio 2.2 正式穩(wěn)定版發(fā)布

  • Android Studio 2.2.2
  • JDK1.7
  • API 24
  • Gradle 2.2.2

NDK和CMake 的下載和安裝

大家可以直接打開SDK進行下載和安裝

SDK

由于NDK的工具包較大, 大家也可以選擇從網(wǎng)站中下載: http://wear.techbrood.com/tools/sdk/ndk/, 選擇自己對應的版本使用迅雷等工具下載即可, 不過通過這種方法一定要修改local.properties文件, 在里面添加:

//后面改成自己下載后解壓的路徑名
ndk.dir=C\:\\Users\\Lulu\\AppData\\Local\\Android\\android-ndk-r13

關于CMake

  1. CMakeList.txt 是腳本文件, 需要指定包含哪些源代碼;
  2. 可以寫一些條件語句, 實現(xiàn)不同的代碼包含
  3. 內部說明:
    add_library 表示編譯一個代碼庫, 內部包含了代碼庫的名稱, 以及源代碼有哪些

NDK兩種開發(fā)模式

  1. ndk-build 形式; Android Studio 2.2之前的模式
  2. CMake 形式: CLion C/C++編輯器; AS2.2之后整合了CLion代碼, AS就支持了CMake形式的NDK開發(fā)

開始開發(fā)

接下來通過幾個案例來演示NDK的開發(fā)流程

創(chuàng)建工程

  1. 新建工程, 選中Include C++ Support


    Include C++ Support
  2. 一路Next之后, 在最后Finish頁面盡量選中圖示兩項, 這樣會給我們包裹一些特定的示例代碼, 幫助我們理解和使用


    NDK
  3. 點擊Finish, 如果出現(xiàn)圖示錯誤的肯定沒有好好看上面的 開發(fā)前準備


    ERROR

案例一 實現(xiàn)在C語言中隱藏AppKey等信息

step1: 為了使代碼整潔, 咱們新建一個類 NativeHelper, 專門用于訪問C語言代碼的幫助類 并添加獲取Appkey的方法


public class NativeHelper {
    static {
        // 加載C代碼庫, 庫的名稱, 必須是CMakeLists.txt中指定的名稱
        System.loadLibrary("native-lib");
    }

    //獲取C中隱藏的AppKey
    public static native String getAppKey();
}

Note: 一定要添加上面的靜態(tài)代碼塊的內容, 否則無法加載C代碼庫
此時的getAppKey()方法標紅, 不用管它, 繼續(xù)....

step2: 在cpp目錄下右擊創(chuàng)建C/C++ Source, 選擇Type, 并勾選 Create an associated hader, 為保持對應, 名字命名為: com_lulu_ndkdemo_NativeHelper, 此時會出現(xiàn), 在cpp目錄下會出現(xiàn)兩個文件, 如圖:

cpp

step3: 在CMakeLists.txt中的add_library中添加依關系, 點擊同步

src/main/cpp/com_lulu_ndkdemo_NativeHelper.c
add_library

Note:

C代碼庫生成的名稱規(guī)則

  1. 如果棧頂代碼庫名稱為 "nh" 那么生成的文件必定是libnh.so
    命名規(guī)則: lib庫名.so
  2. System.loadLibrary(庫名); //此處不能包含前面的lib和后面的.so

step4: 在com_lulu_ndkdemo_NativeHelper.c文件中添加c語言代碼

#include <jni.h>
JNIEXPORT jstring JNICALL
                  Java_com_lulu_ndkdemo_NativeHelper_getAppKey(JNIEnv *env, jclass type) {

    //測試代碼, 沒有任何意義
    char* app_key = "5465465416948";

    //生成 Java 中的字符串對象
    //指針的指針
    // env <=> JNINativeInterface** C語言
    return (*env)->NewStringUTF(env, app_key);
}

step5: 在MainActivity中獲取AppKey, 查看結果 -> 成功


    String appKey = NativeHelper.getAppKey();
    Log.d(TAG, "onCreate: appKey => " + appKey);

Note: Java 調用C/C++代碼

  1. 任何一個類的方法, 如果聲明了native修飾符, 那么就可以認為是一個C代碼;
  1. 可以用對象, 類直接調用
  2. 創(chuàng)建C/C++文件; 如果一個類中有一個native的方法, 那么對應的C方法: Java_包名類名方法名(JNIEnv *env, ...);
  3. 當Java類中包含了native的方法, 那么這個類必須寫一個靜態(tài)初初始化塊: System.loadLibrary("庫名")

案例二 實現(xiàn)在C語言中打印log

接下來, 只簡單介紹核心代碼, 不再贅述

step1: 在com_lulu_ndkdemo_NativeHelper.c中添加:


JNIEXPORT void JNICALL
Java_com_lulu_ndkdemo_NativeHelper_printLog(JNIEnv *env, jclass type, jstring str_) {
    const char *str = (*env)->GetStringUTFChars(env, str_, 0);
    //TODO: 顯示Android 的日志
    // 調用Android的代碼
    // 代碼需要調用系統(tǒng)的日志庫, 這個庫已經(jīng)在 CMakeList.txt添加了e,因此可以直接調用
    const char *tag = "NativeHelper";
    //jstring -> char*
    jboolean b = JNI_FALSE;
    const char* txt = (*env)->GetStringUTFChars(env, str_, b);
    //打印log日志
    __android_log_write(ANDROID_LOG_DEBUG, tag, txt);
    //釋放string
    (*env)->ReleaseStringUTFChars(env, str_, str);
}

step2: NativeHelper中添加

//在C中打印log
public static native void printLog(String str);

step3: MainActivity中調用


//打印C語言中的Log
NativeHelper.printLog("測試Log");

完整代碼

Demo已上傳到github上, 歡迎大家Clone

小結

至此, 咱們應該大致了解了一下NDK開發(fā)的簡單流程, 鄙人菜鳥, 希望拋磚引玉, "引"出更好的文章

本文還有下篇, 將再寫一些關于NDK開發(fā)的案例Demo, 希望大家喜歡和關注

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末徐块,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子灾而,更是在濱河造成了極大的恐慌胡控,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旁趟,死亡現(xiàn)場離奇詭異昼激,居然都是意外死亡,警方通過查閱死者的電腦和手機锡搜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門橙困,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耕餐,你說我怎么就攤上這事凡傅。” “怎么了肠缔?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵夏跷,是天一觀的道長。 經(jīng)常有香客問我明未,道長拓春,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任亚隅,我火速辦了婚禮硼莽,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己懂鸵,他們只是感情好偏螺,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匆光,像睡著了一般套像。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上终息,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天夺巩,我揣著相機與錄音,去河邊找鬼周崭。 笑死柳譬,一個胖子當著我的面吹牛,可吹牛的內容都是我干的续镇。 我是一名探鬼主播美澳,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼摸航!你這毒婦竟也來了制跟?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酱虎,失蹤者是張志新(化名)和其女友劉穎雨膨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體读串,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡哥放,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了爹土。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甥雕。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胀茵,靈堂內的尸體忽然破棺而出社露,到底是詐尸還是另有隱情,我是刑警寧澤琼娘,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布峭弟,位于F島的核電站,受9級特大地震影響脱拼,放射性物質發(fā)生泄漏瞒瘸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一熄浓、第九天 我趴在偏房一處隱蔽的房頂上張望情臭。 院中可真熱鬧,春花似錦、人聲如沸俯在。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跷乐。三九已至肥败,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愕提,已是汗流浹背馒稍。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浅侨,地道東北人纽谒。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像仗颈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子椎例,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容