Android NDK開發(fā)(一) 使用CMake構(gòu)建工具進(jìn)行NDK開發(fā)

封面

2018年的第一篇文章,主要講解了JNI晶密、NDK的一些概念以及在AS 3.0環(huán)境下如何使用CMake構(gòu)建工具來進(jìn)行NDK開發(fā)。

1.了解一些概念

  • JNI(Java Native Interface):

    Java原生接口,是Java和其他原生代碼語言(例如 C 和 C++)通信的橋梁邑时。

  • NDK(Native Development Kit):

    原生開發(fā)工具集,是一套允許您使用原生代碼語言(例如 C 和 C++)實現(xiàn)程序功能的工具集特姐。

  • ABI(Application Binary Interface):

    應(yīng)用程序二進(jìn)制接口晶丘,不同的CPU支持不同的指令集,CPU與指令集的每種組合都有其自己的應(yīng)用二進(jìn)制接口(或ABI)唐含,ABI可以非常精確地定義應(yīng)用的機器代碼在運行時如何與系統(tǒng)交互浅浮。

    ABI官方文檔

    支持的ABI:armeabi、armeabi-v7a觉壶、arm64-v8a脑题、x86、x86_64铜靶、mips叔遂、mips64

  • CMake:

    Android推薦使用的NDK構(gòu)建工具,從AS 2.2版本之后開始支持(包含2.2版本)争剿。

2.環(huán)境搭建

安裝NDK開發(fā)所需的工具

安裝NDK開發(fā)所需的工具

在SDK Tools中安裝以下組件:

  • Cmake:NDK構(gòu)建工具

  • LLDB:NDK調(diào)試工具

  • NDK:NDK開發(fā)工具集

創(chuàng)建NDK項目

創(chuàng)建NDK項目

在創(chuàng)建項目時已艰,勾選【Include C++ support】選項,然后一路下一步蚕苇,到達(dá)【Customize C++ Support】設(shè)置頁:

Customize C++ Support

可以看到三個選項:

  • C++ Standard:C++標(biāo)準(zhǔn)哩掺,選擇【Toolchain Default】會使用默認(rèn)的CMake配置。

  • Exceptions Support:支持C++異常處理涩笤,標(biāo)志為 -fexceptions嚼吞。

  • Runtime Type Information Support:支持運行時類型識別,標(biāo)志為
    -frtti蹬碧,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型舱禽。

在這里我們使用默認(rèn)C++標(biāo)準(zhǔn),不勾選下面的兩個選項恩沽,點擊【Finish】按鈕進(jìn)入下一個環(huán)節(jié)誊稚。

3.NDK項目

看下項目目錄:

項目目錄

上圖中用紅框標(biāo)識了NDK項目與普通項目的不同之處,下面分別來看看:

首先來看下build.gradle配置:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.yl.ndkdemo"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    // 引用一些庫
}

可以看到build.gradle配置中多了兩個externalNativeBuild配置項:

  • defaultConfig里面的:

    主要配置了Cmake的命令參數(shù),例如在創(chuàng)建項目時里伯,如果勾選了【Exceptions Support】和【Runtime Type Information Support】選項城瞎,是這樣配置的:

externalNativeBuild {
    cmake {
        cppFlags "-fexceptions -frtti"
    }
}

更多命令參數(shù)可以查看Android NDK CMake文檔

  • defaultConfig外面的:

    主要定義了CMake的構(gòu)建腳本CMakeLists.txt的路徑。

CMake的構(gòu)建腳本CMakeLists.txt

CMakeLists.txt是CMake的構(gòu)建腳本疾瓮,作用相當(dāng)于ndk-build中的Android.mk脖镀,看下CMakeLists.txt:

# 設(shè)置Cmake最小版本
cmake_minimum_required(VERSION 3.4.1)

# 編譯library
add_library( # 設(shè)置library名稱
             native-lib

             # 設(shè)置library模式
             # SHARED模式會編譯so文件,STATIC模式不會編譯
             SHARED

             # 設(shè)置原生代碼路徑
             src/main/cpp/native-lib.cpp )

# 定位library
find_library( # library名稱
              log-lib

              # 將library路徑存儲為一個變量爷贫,可以在其他地方用這個變量引用NDK庫
              # 在這里設(shè)置變量名稱
              log )

# 關(guān)聯(lián)library
target_link_libraries( # 關(guān)聯(lián)的library
                       native-lib

                       # 關(guān)聯(lián)native-lib和log-lib
                       ${log-lib} )

這是一個基本的CMake構(gòu)建腳本认然,更多腳本配置請參考CMAKE手冊,看不懂漫萄!沒關(guān)系卷员,這里有中文版的CMAKE手冊-中文版

原生代碼native-lib.cpp

Android提供了一個簡單的JNI交互Demo腾务,返回一個字符串給Java層毕骡,方法名是通過 Java_包名_類名_方法名 的方式命名的:

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring

JNICALL
Java_com_yl_ndkdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

看下如何調(diào)用:

public class MainActivity extends AppCompatActivity {

    // 加載native-lib,不加lib前綴
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 將獲取的字符串顯示在TextView上
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * native-lib中的原生方法
     */
    public native String stringFromJNI();
}

調(diào)用方式很簡單岩瘦,代碼中已經(jīng)寫了注釋未巫,看下效果:

運行效果

生成so文件

在CMakeLists.txt中將library的編譯模式設(shè)置為SHARED模式,點擊AS的編譯按鈕启昧,在app > build > intermediates > cmake > debug > obj目錄下會生成不同CPU架構(gòu)對應(yīng)的so文件:

so文件目錄

生成的so文件也可以在其他項目中使用叙凡,在項目的app > src > main目錄下創(chuàng)建jniLibs文件夾,將生成的so文件(帶著CPU架構(gòu)目錄)拷貝到j(luò)niLibs文件夾中密末,按照上文中的調(diào)用方式即可正常使用握爷。

在app的build.gradle文中配置abiFilters,可以輸出指定ABI的so文件:

defaultConfig {
    ...
    
    ndk {
        abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64", "mips", "mips64"
    }
}

4.寫在最后

NDK官方使用文檔

后續(xù)還會更新更多NDK開發(fā)系列文章严里,敬請期待新啼!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市刹碾,隨后出現(xiàn)的幾起案子燥撞,更是在濱河造成了極大的恐慌,老刑警劉巖迷帜,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件物舒,死亡現(xiàn)場離奇詭異,居然都是意外死亡戏锹,警方通過查閱死者的電腦和手機冠胯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來景用,“玉大人涵叮,你說我怎么就攤上這事∩〔澹” “怎么了割粮?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長媚污。 經(jīng)常有香客問我舀瓢,道長,這世上最難降的妖魔是什么耗美? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任京髓,我火速辦了婚禮,結(jié)果婚禮上商架,老公的妹妹穿的比我還像新娘堰怨。我一直安慰自己,他們只是感情好蛇摸,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布备图。 她就那樣靜靜地躺著,像睡著了一般赶袄。 火紅的嫁衣襯著肌膚如雪揽涮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天饿肺,我揣著相機與錄音蒋困,去河邊找鬼。 笑死敬辣,一個胖子當(dāng)著我的面吹牛雪标,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播购岗,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼汰聋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喊积?” 一聲冷哼從身側(cè)響起烹困,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乾吻,沒想到半個月后髓梅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡绎签,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年枯饿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诡必。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡奢方,死狀恐怖搔扁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蟋字,我是刑警寧澤稿蹲,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站鹊奖,受9級特大地震影響苛聘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜忠聚,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一设哗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧两蟀,春花似錦网梢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至欢瞪,卻和暖如春活烙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遣鼓。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工啸盏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骑祟。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓回懦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親次企。 傳聞我的和親對象是個殘疾皇子怯晕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353