NDK與JNI的基礎(chǔ)與基本配置和使用


一乡数、NDK

什么是NDK炼绘?

在Android OS上開發(fā)應(yīng)用程序嗅战,Google提供了兩種開發(fā)包:SDK和NDK。

NDK---全稱:Native Develop Kit俺亮,是Android的一個工具開發(fā)包

Android的開發(fā)語言是Java驮捍,而且Android是基于Linux的,其核心庫很多都是C/C++代碼的一個工作脚曾。NDK其實本身其實就是一個交叉工作鏈嘹悼,包含了Android上的一些庫文件义钉,而且NDK為了方便使用心赶,提供了一些腳本严沥,使得更容易編譯C/C++代碼。簡單的來說囤踩,Android NDK就是一套工具集合旨椒,允許你使用C/C++語言來實現(xiàn)應(yīng)用程序的部分功能。

為什么要使用NDK堵漱?NDK的優(yōu)點综慎?


NDK特點.png

作用

快速開發(fā)c、c++的動態(tài)庫勤庐,并自動將so和應(yīng)用一起打包成APK示惊,即可通過NDK在android中,使用JNI與本地代碼(如c愉镰、c++)交互

應(yīng)用場景

在Android的場景下使用JNI即Android開發(fā)的功能需要本地代碼(c\c++)實現(xiàn)

額外注意

NDK提供了把.so和.apk打包的工具,而JNI開發(fā)沒有米罚,只是把.so文件放到文件按系統(tǒng)的特定位置

NDK提供的庫有限,僅用于處理算法效率和處理敏感的問題

提供了交叉編譯器丈探,用于生成特定的CPU平臺動態(tài)庫

NDK到SO

因為C語言的不跨平臺性录择,需要使用NDK編譯Linux下能執(zhí)行的函數(shù)庫---so文件(其本質(zhì)就是一堆C、C++的頭文件和實現(xiàn)文件打包成一個庫)目前Android系統(tǒng)支持以下七種不用的CPU架構(gòu),每一種對應(yīng)著各自的應(yīng)用程序二進制接口ABI:(Application Binary Interface)定義了二進制文件(尤其是.so文件)如何運行在相應(yīng)的系統(tǒng)平臺上隘竭,從使用的指令集塘秦,內(nèi)存對齊到可用的系統(tǒng)函數(shù)庫。對應(yīng)關(guān)系如下:

ARMv5——armeabi

ARMv7 ——armeabi-v7a

ARMv8——arm64- v8a

x86——x86

MIPS ——mips

MIPS64——mips64

x86_64——x86_64


二动看、JNI

什么是JNI尊剔?

JNI,全稱:Java Native Interfave,即Java本地接口菱皆,JNI是Java調(diào)用Native語言的一種特性须误。通過JNI可以使得Java與C/C++交互,即可以在Java代碼中調(diào)用C/C++等語言的代碼或者在C/C++代碼中調(diào)用Java代碼仇轻。

但是開發(fā)JNI程序會受到系統(tǒng)環(huán)境限制京痢,因為用C/C++ 語言寫出來的代碼或模塊,編譯過程當(dāng)中要依賴當(dāng)前操作系統(tǒng)環(huán)境所提供的一些庫函數(shù)拯田,并和本地庫鏈接在一起历造。而且編譯后生成的二進制代碼只能在本地操作系統(tǒng)環(huán)境下運行,因為不同的操作系統(tǒng)環(huán)境船庇,有自己的本地庫和CPU指令集,這個時候就需要NDK將本地代碼在不同的操作系統(tǒng)平臺下編譯出相應(yīng)的動態(tài)庫侣监。

為什么需要JNI

實際使用中鸭轮,java需要與本地代碼進行交互,因為java具備跨平臺的特點橄霉,所以java與本地代碼交互能力非常弱窃爷,所以采用JNI特性增強java與本地代碼交互的能力。

作用

使得java與本地其他類型語言(如c姓蜂、c++)交互即在java代碼里調(diào)用c按厘、c++等語言的代碼或c、c++代碼調(diào)用java代碼钱慢。

JNI開發(fā)流程6步驟

1.編寫聲明了native方法的Java類

2.將Java源代碼編譯成class字節(jié)碼文件

3.用javah -jni命令生成.h頭文件(javah是jdk自帶的一個命令逮京,-jni參數(shù)表示將class中用native聲明的函數(shù)生成JNI規(guī)則的函數(shù))

4.用本地代碼實現(xiàn).h文件中的函數(shù)

5.將本地代碼編譯成動態(tài)庫(Windows:\*.dll,linux/unix:\*.so,mac os x:\*.jnilib)

6.拷貝動態(tài)庫至java.library.path本地庫搜索目錄下,并運行Java程序束莫。

特別注意

1.JNI是java調(diào)用Native語言的一種特性

2.JNI是屬于java的懒棉,與Android無直接關(guān)系


三、在Android studio中配置---我使用的是Android studio3.4.1

1.下載NDK

首先找到studio右上角的SDK Manager 并點擊

SDK Manager.png

然后找到下方的SDK tools览绿,找到LLDB,CMake,NDK下載策严,然后apply 和OK 即可

NDK下載.png

接著找到我們的SDK location,然后將NDK的路徑填寫在紅框中的地方饿敲,如果是studio中下載的SDK妻导,路徑就在配置的sdk文件夾中,配置好后點擊OK 即可

配置NDK路徑.png

SDK以及NDK的路徑配置會保存在local.properties文件內(nèi),安裝完成后刷新Project倔韭,進local.properties文件查看就能看到SDK與NDK的路徑术浪。

local.properties中查看NDK和SDK的路徑.png

注意:以前有些版本需要在gradle.properties文件中加上一行android.useDeprecatedNdk=true,3.0版本不再支持了狐肢。

2.添加插件

為省去控制臺輸入命令麻煩添吗。我們借助強大的Android Studio的插件功能,在External Tools下配置兩個非常有用的插件份名。進入Setting->Tools->ExternalTools,點擊+號增加碟联。

javah -jni命令

Androidstudio添加插件.png
javah -jni命令.png

javah -jni命令,根據(jù)java文件生成.h頭文件僵腺,會自動根據(jù)java文件中的類名(包含包名)與方法名生成對應(yīng)的C/C++里面的方法名鲤孵。下面是參數(shù)配置及其含義:

1.Program:$JDKPath$\bin\javah\java.exe這里配置的是JDK目錄下的javah.exe的路徑。

2.Arguments:-classpath $ModuleFileDir$\src\main\java -jni -d $ModuleFileDir$\src\main\jni $FileClass$

注:在老版本的studio中沒有Arguments辰如,為Parametes:-classpath .-jni -d $ModuleFileDir$/src/main/jni $FileClass$ 這里$FileClass$指的是要執(zhí)行操作的類名(類的全名(包名+類名))(即我們操作的文件)普监,$ModuleFileDir$/src/main/jni表示生成的文件保存在這個module目錄的src/main/jni目錄下。

3.Working :$ModuleFileDir$\src\main\java表示module目錄下的src\main\java目錄琉兜。使用方式:選中java文件->右鍵->External Tools->javah -jni,將生成jni文件夾以及文件夾下的包名.類名的.h頭文件(名字有點長凯正,可以自己重命名)。

ndk -build命令

ndk -build命令.png

ndk -build命令,是根據(jù)C/C++文件生成so文件的豌蟋。下面是參數(shù)配置及其含義:

1.Program:F:\apk\sdk\ndk-bundle\ndk-build.cmd這里配置的是ndk下的ndk-build.cmd的路徑(根據(jù)實際情況填寫

2.Working:$ModuleFileDir$\src\main\

使用方法:選中C/C++文件->右鍵->External Tools->ndk-build,將在main文件夾下生成libs文件夾以及多個so文件廊散,我們可以移動至jniLibs目錄下去。

四梧疲、簡單使用

1.創(chuàng)建java類隨意創(chuàng)建一個訪問本地C/C++方法的java類允睹,生成.h頭文件,然后對該文件執(zhí)行javah -jni操作幌氮,生成對應(yīng)的.h頭文件缭受。

創(chuàng)建.h文件


生成的.h文件

如圖,已經(jīng)根據(jù)我們的java類在jni文件夾下生成了對應(yīng)的.h文件该互,文件名為包名類名.h米者,我們可以手動改.h文件名,里面只有一個方法慢洋,返回值為String(jstring)塘雳,方法名為java類的包名類名方法名(包名中的分級不是用.而是_),前面兩個參數(shù)是C++里面必須有的(JNIEnv代表指向JVM的指針普筹,jclass是調(diào)用該方法的java對象)败明,第三個jobject就是我們java類的方法里面的參數(shù)Object。注意太防,這是java函數(shù)與C++函數(shù)對應(yīng)的靜態(tài)注冊方法妻顶,即通過特定的規(guī)則來寫酸员。此處方法名可以隨意起名字,然后還可以用動態(tài)注冊的方式關(guān)聯(lián)兩個方法讳嘱。

2.創(chuàng)建c或c++文件

在jni文件夾下幔嗦,新建一個.c(c語言)或者.cpp(C++)的文件,來實現(xiàn).h文件里聲明的方法:

把.h文件里面聲明的方法拷貝到新建的c文件里面沥潭,然后在文件里面引入.h文件邀泉,如下圖:

.c文件

至此,.h文件和c++文件已完成钝鸽,想生成so文件還需要在這個jni目錄下增加兩個文件汇恤,Android.mk和Application.mk。

Android.mk

注意LOCAL_MODULE的值與之前的java類中設(shè)置要生成so庫的名字相對應(yīng)拔恰,LOCAL_SRC_FILES的值寫C++文件的名字因谎,這兩個值成對設(shè)置,可設(shè)置多組颜懊。(:=是賦值的意思财岔,$是引用某變量的值)

LOCAL_PATH := $(call my-dir) ????// 設(shè)置當(dāng)前的編譯目錄(Android.mk所在的目錄)

include $(CLEAR_VARS) ???????????// 清除LOCAL_XX變量(LOCAL_PATH除外)

LOCAL_MODULE := myLib // 指定當(dāng)前編譯模塊的名稱 ?

LOCAL_SRC_FILES := jnittest.c ???// 編譯模塊需要的源文件

include $(BUILD_SHARED_LIBRARY)

?// 指定編譯出的庫類型,BUILD_SHARED_LIBRARY:動態(tài)庫河爹;BUILD_STATIC_LIBRARY:靜態(tài)庫匠璧, BUILD_EXECUTEABLE指:可執(zhí)行文件


Android.mk文件

在一個Android.mk文件中配置多個Module的方式如下(include $(CLEAR_VARS)、include $(BUILD_SHARED_LIBRARY)兩個語句也需要加上)

LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)

LOCAL_MODULE := myLib

LOCAL_SRC_FILES := jnittest.c

include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)

LOCAL_MODULE := myLib2

LOCAL_SRC_FILES := jnittest2.c

include $(BUILD_SHARED_LIBRARY)

Application.mk

Application.mk咸这,APP_ABI有四種類型(默認armeabi)患朱,armeabi、armeabi-v7a炊苫、x86、mips冰沙,設(shè)置時以空格隔開侨艾,all表示所有。該文件中有個可選配置的APP_MODULES,類似于上面Android.mk文件中的LOCAL_MODUEL,以空格隔開拓挥,且會覆蓋掉Android.mk文件中的LOCAL_MODULE設(shè)置(比如Android.mk文件中的寫了兩個jni庫的配置唠梨,LOCAL_MODULE:=JNI1、LOCAL_MODULE:=JNI2,而Application.mk中設(shè)置的APP_MODULES:=JNI1,則只能生成JNI1的so文件侥啤,要生成JNI2的so文件的時候會報錯当叭,除非寫成APP_MODULE:=JNI1 JNI2,這里我們直接省略默認使用Android.mk中的)

APP_ABI := all

生成so文件

對C++文件執(zhí)行ndk-build操作,生成相應(yīng)的so文件


生成so文件


so文件

如圖盖灸,在main/libs目錄下生成了多個so文件蚁鳖,名字為lib+我們指定的庫名(同時還生成了obj文件夾,中間文件)赁炎。這時候我們可以生成的main/libs文件夾內(nèi)的東西復(fù)制到app/libs下醉箕,并刪除main下新生成的jni、libs、obj三個文件夾讥裤。

在項目的build.gradle中配置app/gradle

配置so文件

調(diào)用

在Activity中測試調(diào)用放棒,在TextView上顯示我們通過C++代碼實現(xiàn)的方法getStrFromC獲取字符串。

//配置加載的so庫的文件名字===>如 :libmyLib.so */

?static { ?

?????? System.loadLibrary("myLib");

?}

使用

Android studio 下載NDK和構(gòu)建工具

1.Android原生開發(fā)工具包(NDK):這套工具集允許您開發(fā)Android使用C和C++代碼己英,并提供眾多平臺庫间螟,讓您可以管理原生Activity和訪問物理設(shè)備組件,例如傳感器和觸摸輸入损肛。

2.CMake:一款外部構(gòu)建工具厢破,可與Gradle搭配使用來構(gòu)建原生庫。如果您只計劃使用ndk-build荧关,則不需要此組件溉奕。

3.LLDB:一種調(diào)試程序,Android Studio使用它來調(diào)試原生代碼忍啤。

注:在前面下載ndk的時候已經(jīng)提示過如何下載

創(chuàng)建支持C/C++的新項目

創(chuàng)建支持原生代碼的項目與創(chuàng)建任何其他Android Studio項目類似加勤,不過支持原生代碼的項目還需要額外幾個步驟:

1.在向?qū)У?b>Configure your new project部分,選中Include C++ Support復(fù)選框同波。

2.點擊Next鳄梅。

3.正常填寫所有其他字段并完成向?qū)Ы酉聛淼膸讉€部分。

4.在向?qū)У?b>Customize C++ Support部分未檩,您可以使用下列選項自定義項目


1.C++ Standard:使用下拉列表選擇您希望使用哪種C++標準戴尸。選擇 Toolchain Default 會使用默認的CMake 設(shè)置,這個選項如果你現(xiàn)在還不確定該選哪個冤狡,最好選擇C++11的標準孙蒙。

2.Exceptions Support:如果您希望啟用對C++異常處理的支持,請選中此復(fù)選框悲雳。如果啟用此復(fù)選框挎峦,Android Studio 會將 -fexceptions 標志添加到模塊級 build.gradle 文件的 cppFlags 中,Gradle 會將其傳遞到 CMake合瓢。

3.Runtime Type Information Support:如果您希望支持RTTI坦胶,請選中此復(fù)選框。如果啟用此復(fù)選框晴楔,Android Studio 會將 -frtti 標志添加到模塊級 build.gradle 文件的 cppFlags 中顿苇,Gradle 會將其傳遞到 CMake。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末税弃,一起剝皮案震驚了整個濱河市纪岁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钙皮,老刑警劉巖蜂科,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顽决,死亡現(xiàn)場離奇詭異,居然都是意外死亡导匣,警方通過查閱死者的電腦和手機才菠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贡定,“玉大人赋访,你說我怎么就攤上這事』捍” “怎么了蚓耽?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長旋炒。 經(jīng)常有香客問我步悠,道長,這世上最難降的妖魔是什么瘫镇? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任鼎兽,我火速辦了婚禮,結(jié)果婚禮上铣除,老公的妹妹穿的比我還像新娘谚咬。我一直安慰自己,他們只是感情好尚粘,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布择卦。 她就那樣靜靜地躺著,像睡著了一般郎嫁。 火紅的嫁衣襯著肌膚如雪秉继。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天泽铛,我揣著相機與錄音秕噪,去河邊找鬼。 笑死厚宰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遂填。 我是一名探鬼主播铲觉,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吓坚!你這毒婦竟也來了撵幽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤礁击,失蹤者是張志新(化名)和其女友劉穎盐杂,沒想到半個月后逗载,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡链烈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年厉斟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片强衡。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡擦秽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出漩勤,到底是詐尸還是另有隱情感挥,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布越败,位于F島的核電站触幼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏究飞。R本人自食惡果不足惜置谦,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望噪猾。 院中可真熱鬧霉祸,春花似錦、人聲如沸袱蜡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坪蚁。三九已至奔穿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敏晤,已是汗流浹背贱田。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘴脾,地道東北人男摧。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像译打,于是被迫代替她去往敵國和親耗拓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容