Android NDK初探

之前對NDK開發(fā)一直是個(gè)小白往湿,最近花了幾天時(shí)間研究得到的一些理解在此做個(gè)記錄分享妖异。結(jié)論不足之處拒絕反駁惨好,所有觀點(diǎn)僅單方面宣布,后果自負(fù)随闺。*.*,本文出處:http://www.reibang.com/p/201046751a7c

一蔓腐、什么是NDK矩乐?

NDK全稱是Native Development Kit(原生開發(fā)工具包),NDK提供了一系列的工具回论,幫助開發(fā)者快速開發(fā)C(或C++)的動態(tài)庫散罕,并能自動將so和java應(yīng)用一起打包成apk。也就是說它是一個(gè)“開發(fā)工具包”傀蓉,就像SDK一樣欧漱,區(qū)別就在于SDK是面向java開發(fā)者的工具集合,而NDK面向的則是C/C++開發(fā)者的工具集合(包括對c/c++源碼的打包編譯工具ndk葬燎,一些h頭文件等)误甚。附上官方NDK工具包的下載路徑:官網(wǎng)ndk下載,需要翻墻谱净。

二窑邦、為什么需要使用NDK?

1.代碼的保護(hù)壕探。由于apk的java層代碼很容易被反編譯冈钦,而C/C++庫反匯難度較大。
2.可以方便地使用現(xiàn)存的開源庫李请。大部分現(xiàn)存的開源庫都是用C/C++代碼編寫的瞧筛。
3.提高程序的執(zhí)行效率。將要求高性能的應(yīng)用邏輯使用C開發(fā)导盅,從而提高應(yīng)用程序的執(zhí)行效率较幌。
4.便于移植。用C/C++寫得庫可以方便在其他的嵌入式平臺上再次使用认轨。

三绅络、JNI、SO介紹

JNI 全稱Java Native Interface嘁字,這套技術(shù)的機(jī)制是用于java訪問c/c++代碼而產(chǎn)生的恩急,說白了NDK開發(fā)的核心就是JNI開發(fā),利用java代碼來調(diào)用遵循JNI規(guī)范的c/c++的方法實(shí)現(xiàn)某個(gè)功能纪蜒。

so全稱Shared Object衷恭,本地原生庫,先暫時(shí)理解為java中的jar包纯续,所有的c/c++的代碼在android(Linux)平臺中最終都會編譯成so庫随珠,然后才能被調(diào)用灭袁。所以ndk開發(fā)所編寫出的c/c++代碼最終的目的都是為了獲得這個(gè)so庫,與java方法形成jni的映射關(guān)系從實(shí)現(xiàn)調(diào)用窗看。

四乙各、開始擼碼

本文使用Android Studio2.0進(jìn)行演示HelloJni

? 大概步驟:

? ? ?1. java文件中聲明native方法翻具,和java方法聲明一樣,在此基礎(chǔ)上加了natvie修飾。
? ? ?2. 利用javah命令生成與該類對應(yīng)的頭文件(包含方法信息)
? ? ?3. 根據(jù)頭文件的信息編寫c源代碼文件
? ? ?4. 在app\build.gradle文件中配置ndk的編譯信息
? ? ?5. 配置NDK工具包路徑级乐,編譯運(yùn)行

創(chuàng)建項(xiàng)目:HelloJni

圖 1

1. 定義一個(gè)java類SayHello迈着,并在里面聲明一個(gè)靜態(tài)無參native方法speak竿拆,并且創(chuàng)建jni文件夾

圖 2

2. 利用javah命令生成與該類對應(yīng)的jni頭文件挑辆,生成的頭文件的目的主要是用來編寫c/c++源文件

圖 3

3.根據(jù).h頭文件的信息編寫c源代碼文件 : 創(chuàng)建SayHello.c文件,把頭文件里的方法copy到該文件中魔慷,并修改成實(shí)體方法只锭,下面則是返回一段字符串。如果熟悉了jni方法名稱命名規(guī)范院尔,完全可自己手寫蜻展,生成頭文件的步驟也可跳過。親測發(fā)現(xiàn)如果包名帶有數(shù)字的命名規(guī)則不好把握邀摆,所以建議用javah生成铺呵。

圖 4

4.在build.gradle中配置ndk的編譯信息,配置完成保存同步之后可能出現(xiàn)錯(cuò)誤隧熙,添加 android.useDeprecatedNdk=true 到gradle.properties 文件中即可解決片挂。

圖 5

5.配置下載好的NDK工具包:File->Project Structure->SDK Location(文件路徑\android-ndk-r14b目錄配置到系統(tǒng)環(huán)境變量中,以備后面使用)

圖 6

然后回到在java文件中贞盯,加載buil.gradle中配置的moduleName的類庫名稱音念,這里配置為:SayHello

圖 7

最后在MainActivity中測試該方法。

圖 8

運(yùn)行躏敢。

圖 9


至此闷愤,體驗(yàn)了一把基本的ndk開發(fā)過程。不過洗腦還沒有結(jié)束:

在運(yùn)行完成之后件余,我們并沒有發(fā)現(xiàn)工程目錄中有so庫文件讥脐,其實(shí)這個(gè)so庫文件是在運(yùn)行之后直接打包到了apk文件中的lib目錄下了

圖 10

由于我們在build.gradle配置了abiFilters打包時(shí)只打包x86的文件夾中的so庫。所以我們在apk中只看到x86的文件夾啼器,里面存放的就是so庫旬渠,如果不配置abiFilters,那么將會出現(xiàn)android支持的7種abi端壳,可參見該文章理解ABI告丢。

因?yàn)槲覀兛梢哉{(diào)用so這個(gè)庫,顯然這個(gè)so庫是根據(jù)我們在jni文件夾下編寫的源文件編譯生成的损谦,如果我們沒有配置岖免,gradle默認(rèn)就會去編譯jni的文件夾下的c/c++的代碼生成so庫岳颇,這個(gè)路勁就是src/main/jni,如果這個(gè)文件夾沒有文件即使配置了ndk{...}信息也不會生成so庫颅湘,當(dāng)然gradle還提供自定義配置话侧,下面就看看如何配置:

sourceSets{
 ?main{
 ? ?jin.srcDirs=["src/mian/jni"] ?//默認(rèn)路徑,jin.srcDirs指的是需要加入編譯的jni的路徑闯参,可以自己修改路徑的
 ?}
}
圖 11

這個(gè)apk安裝到x86 abi手機(jī)上之后掂摔,so庫會安裝在data\app\包名-數(shù)值\ib目錄下(可通過Device Monitor工具查看),所以由此可判斷System.loadLibrary()加載的庫默認(rèn)是這個(gè)路徑下的庫赢赊,也可以調(diào)用System.load(data\app\包名-數(shù)值\ib\abi\libxx.so)加載絕對路徑的so庫。

圖 12

所以java代碼能不能正確的執(zhí)行so庫里的內(nèi)容取決于so庫能否被正確的安裝级历。如果未能正確安裝释移,當(dāng)虛擬機(jī)去System.loadLibrary時(shí)就會報(bào)錯(cuò)java.lang.UnsatisfiedLinkError

上面的做法只有在打包時(shí)才能得到so庫寥殖,下面就介紹通過ndk開發(fā)工具包里的ndk-build單獨(dú)來編譯出so庫玩讳,這種方式就無需在build.gradle中配置ndk{...}了。

1. 在jni文件家中新建android.mk編譯配置文件嚼贡,參見Android.mk詳細(xì)配置

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE ? ?:= SayHello
LOCAL_SRC_FILES := SayHello.c

include $(BUILD_SHARED_LIBRARY)

2.在jni文件家中新建application.mk配置需要生成支持的abi so庫熏纯,參見Application.mk詳細(xì)配置

APP_CFLAGS += -Wno-error=format-security
APP_ABI := all

這里配置支持所有的abi。

3.在terminal中調(diào)用ndk-build工具生成so庫

圖 13

我們可以看到在main文件夾下生成了libs目錄粤策,并且生成了支持所有abi的so庫樟澜,到此生成so完畢;現(xiàn)在任務(wù)就是要讓這些so庫打包到apk文件中的libs目錄下叮盘,在build.gradle中配置sourceSets的另一個(gè)屬性jniLibs.srcDirs秩贰,配置的路徑下的so庫文件都會打包到apk文件中,其默認(rèn)值為app/libs柔吼,所以也可以把這些so文件拷到app/libs中而不配置這個(gè)屬性用其默認(rèn)值毒费。

圖 14

上圖中不配置jni.srcDirs的路徑的作用是為了打包時(shí)不讓編譯系統(tǒng)再去編譯得到so庫(因?yàn)槲覀円呀?jīng)單獨(dú)生成),雖然上面ndk沒有被配置愈魏,但是只要的配置這個(gè)路徑下有c文件就會生成so庫觅玻,并且名字為libapp.so,這樣一來就造成了相同的包存在兩個(gè)增加app的體積培漏。

最后build apk看看apk里有沒有so庫:


圖 15

運(yùn)行溪厘,大功告成。

下一篇文章介紹:第三方so庫的調(diào)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牌柄,一起剝皮案震驚了整個(gè)濱河市桩匪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌友鼻,老刑警劉巖傻昙,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闺骚,死亡現(xiàn)場離奇詭異,居然都是意外死亡妆档,警方通過查閱死者的電腦和手機(jī)僻爽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贾惦,“玉大人胸梆,你說我怎么就攤上這事⌒氚澹” “怎么了碰镜?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長习瑰。 經(jīng)常有香客問我绪颖,道長,這世上最難降的妖魔是什么甜奄? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任柠横,我火速辦了婚禮,結(jié)果婚禮上课兄,老公的妹妹穿的比我還像新娘牍氛。我一直安慰自己,他們只是感情好烟阐,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布搬俊。 她就那樣靜靜地躺著,像睡著了一般蜒茄。 火紅的嫁衣襯著肌膚如雪悠抹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天扩淀,我揣著相機(jī)與錄音楔敌,去河邊找鬼。 笑死驻谆,一個(gè)胖子當(dāng)著我的面吹牛卵凑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胜臊,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼勺卢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了象对?” 一聲冷哼從身側(cè)響起黑忱,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后甫煞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菇曲,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年抚吠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了常潮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡楷力,死狀恐怖喊式,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萧朝,我是刑警寧澤岔留,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站检柬,受9級特大地震影響献联,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜厕吉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望械念。 院中可真熱鬧头朱,春花似錦、人聲如沸龄减。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽希停。三九已至烁巫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宠能,已是汗流浹背亚隙。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留违崇,地道東北人阿弃。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像羞延,于是被迫代替她去往敵國和親渣淳。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評論 25 707
  • 一伴箩、NDK產(chǎn)生的背景 Android平臺從誕生起入愧,就已經(jīng)支持C、C++開發(fā)。眾所周知棺蛛,Android的SDK基于J...
    Ten_Minutes閱讀 3,479評論 1 27
  • 本人為初學(xué)者怔蚌,文章寫得不好,如有錯(cuò)誤鞠值,請大力懟我 或者看這里 如何使用jni進(jìn)行開發(fā) 本文主要針對Android環(huán)...
    AlbertHumbert閱讀 4,643評論 2 12
  • Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)02 承接上篇Android游戲開發(fā)實(shí)踐(1)之NDK與JNI...
    AlphaGL閱讀 3,740評論 0 24
  • 若你愿獻(xiàn)祭 我會在你的乳上 劃一道傷口 輕輕舔起 若你愿獻(xiàn)祭 我會在皮鞭和你之間 鋪散烏賊的氣息 圖畫現(xiàn)代性的隨機(jī)...
    主修寂靜閱讀 213評論 0 0