Android JNI和NDK簡(jiǎn)單使用

一:JNI介紹

1.簡(jiǎn)介:Java Native Interface哼拔,即java本地接口,本地接口就是指用C和C++開(kāi)發(fā)的接口。

2.由來(lái):實(shí)際使用中,java需要與本地代碼進(jìn)行交互级乍,因?yàn)閖ava具備跨平臺(tái)的特點(diǎn),所以java與本地代碼交互能力非常弱帚湘,所以采用JNI特性增強(qiáng)java與本地代碼交互的能力玫荣。

3.作用:使得java與本地其他類型語(yǔ)言(如c、c++)交互大诸,即在java代碼里調(diào)用c捅厂、c++等語(yǔ)言的代碼或c、c++代碼調(diào)用java代碼底挫。

4.JNI開(kāi)發(fā)主要流程:

(1) 編寫(xiě)聲明了native方法的Java類

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

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

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

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

(6) 拷貝動(dòng)態(tài)庫(kù)至java.library.path本地庫(kù)搜索目錄下,并運(yùn)行Java程序建邓。

5.注意點(diǎn):(1) JNI是java調(diào)用Native語(yǔ)言的一種特性, (2) JNI是屬于java的盈厘,與Android沒(méi)有直接關(guān)聯(lián)。

二:NDK介紹

1.簡(jiǎn)介:Native Development Kit官边,是Android的一個(gè)開(kāi)發(fā)工具包沸手,NDK是屬于Android,與java沒(méi)有直接關(guān)聯(lián)

2.作用:快速開(kāi)發(fā)c注簿、c++的動(dòng)態(tài)庫(kù)契吉,并自動(dòng)將so和應(yīng)用一起打包成APK即可通過(guò)NDK在android中,使用JNI與本地代碼(如c诡渴、c++)交互捐晶。

3.應(yīng)用場(chǎng)景:在Android的場(chǎng)景下使用JNI即Android開(kāi)發(fā)的功能需要本地代碼(c\c++)實(shí)現(xiàn)。

4.特點(diǎn):用下面的圖來(lái)直觀的了解它的特點(diǎn)

5.使用流程:

(1) 配置Android NDK環(huán)境

(2) 創(chuàng)建Android項(xiàng)目妄辩,并于NDK關(guān)聯(lián)

(3) 在Android項(xiàng)目中生命所需要調(diào)用的Native方法

(4) 使用Android需要交互的本地代碼惑灵,實(shí)現(xiàn)在Android中聲明的Native方法,比如Android需要與C++交互,那么就用C++實(shí)現(xiàn)Java的Native方法

(5) 通過(guò)ndk-build命令編譯產(chǎn)生.so庫(kù)文件

(6) 編譯Android Studio工程眼耀,從而實(shí)現(xiàn)Android 調(diào)用本地代碼

6.額外注意點(diǎn):

三:NDK與JNI關(guān)系:

1.NDK與JNI關(guān)系:NDK可以為我們生成了C/C++的動(dòng)態(tài)鏈接庫(kù)英支,JNI是java和C/C++溝通過(guò)的接口,兩者與android沒(méi)有半毛錢(qián)關(guān)系哮伟,只因?yàn)榘沧渴莏ava程序語(yǔ)言開(kāi)發(fā)干花,然后通過(guò)JNI又能與C/C++溝通,所以我們可以使用NDK+JNI來(lái)實(shí)現(xiàn)Java+C的開(kāi)發(fā)方式楞黄。

2.使用NDK開(kāi)發(fā)的好處:

(1) 項(xiàng)目需要調(diào)用底層的一些C/C++的一些東西(java無(wú)法直接訪問(wèn)到操作系統(tǒng)底層(系統(tǒng)硬件等))池凄,或者已經(jīng)在C/C++環(huán)境下實(shí)現(xiàn)了功能代碼(大部分現(xiàn)存的開(kāi)源庫(kù)都是用C/C++代碼編寫(xiě)的。)直接使用即可

(2) 為了效率更加高效些谅辣。將要求高性能的應(yīng)用邏輯使用C/C++開(kāi)發(fā)修赞,從而提高應(yīng)用程序的執(zhí)行效率。但是C/C++代碼雖然是高效的,在java與C/C++相互調(diào)用時(shí)卻增大了開(kāi)銷

(3) 基于安全性考慮柏副。防止代碼被反編譯勾邦,為了安全起見(jiàn),使用C/C++語(yǔ)言來(lái)編寫(xiě)重要的部分以增大系統(tǒng)的安全性割择,最后生成so庫(kù)(用過(guò)第三方庫(kù)的應(yīng)該都不陌生)便于給人提供方便

(4) 便于移植眷篇。用C/C++寫(xiě)的庫(kù)可以方便在其他的嵌入式平臺(tái)上再次使用

四:配置及具體使用

1.下載安裝NDK:NDK的下載方式有兩種方式,可以直接去 https://developer.android.com/ndk/downloads?hl=zh-cn荔泳;另一種就是直接在我們的Android Studio中下載蕉饼,打開(kāi)我們Studio項(xiàng)目下的Project Structure界面,如下:

在SDK Location目錄下玛歌,有SDK和NDK的路徑昧港,我這里已經(jīng)安裝NDK。如果還沒(méi)有安裝配置過(guò)NDK支子,Android Studio會(huì)提示下載Android NDK如下圖:

點(diǎn)擊Download Android NDK來(lái)進(jìn)行下載创肥。這里Android Studio會(huì)下載最新版本的NDK進(jìn)行安裝,默認(rèn)會(huì)下載保存在SDK的路徑下值朋。我們?cè)谏蠄D中還能看到有一段介紹文字叹侄,說(shuō)SDK以及NDK的路徑配置會(huì)保存在local.properties文件內(nèi),安裝完成后我們刷新Project昨登,進(jìn)local.properties文件查看也能看到SDK與NDK的路徑趾代。

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

2.添加插件:為了省去控制臺(tái)輸入命令麻煩撒强。我們借助強(qiáng)大的Android Studio的插件功能,在External Tools下配置兩個(gè)非常有用的插件笙什。進(jìn)入Setting->Tools->ExternalTools,點(diǎn)擊+號(hào)增加尿褪,如下圖:

3.javah -jni命令:根據(jù)java文件生成.h頭文件,會(huì)自動(dòng)根據(jù)java文件中的類名(包含包名)與方法名生成對(duì)應(yīng)的C/C++里面的方法名得湘。

參數(shù)及其含義:

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

(2) Parametes:-classpath .-jni -d $ModuleFileDir$/src/main/jni $FileClass$ 這里$FileClass$指的是要執(zhí)行操作的類名(類的全名(包名+類名))(即我們操作的文件),$ModuleFileDir$/src/main/jni表示生成的文件保存在這個(gè)module目錄的src/main/jni目錄下

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

4.ndk-build命令:

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

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

(2) Working:$ModuleFileDir$\src\main\

5.使用方法:選中C/C++文件->右鍵->External Tools->ndk-build,將在main文件夾下生成libs文件夾以及多個(gè)so文件臼闻,我們可以移動(dòng)至jniLibs目錄下去鸿吆,接下來(lái)通過(guò)一個(gè)簡(jiǎn)單的實(shí)例來(lái)了解它的使用。

(1) 創(chuàng)建Java類:隨意創(chuàng)建一個(gè)訪問(wèn)本地C/C++方法的java類:

? ? ? ? public class JniTest {

? ? ? ? /** * 將用C++代碼實(shí)現(xiàn)述呐,在android代碼中調(diào)用的方法:獲取一段文字 */ public static native String? ? ? ? getStrFromC();

? ? ? ? /** * 配置加載的so庫(kù)的文件名字===>如 :libmyLib.so */

? ? ? ? static {?

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

? ? ? ? ? ? }

? ? ? ? }

(2) 該類的getStrFromC會(huì)報(bào)錯(cuò)提示惩淳,不用管。

生成.h頭文件:對(duì)該文件執(zhí)行javah -jni操作,生成對(duì)應(yīng)的.h頭文件思犁。

如圖代虾,已經(jīng)根據(jù)我們的java類在jni文件夾下生成了對(duì)應(yīng)的.h文件,文件名為包名類名.h激蹲,我們可以手動(dòng)改.h文件名棉磨,里面只有一個(gè)方法,返回值為String(jstring)学辱,方法名為java類的包名類名方法名(包名中的分級(jí)不是用.而是_)乘瓤,前面兩個(gè)參數(shù)是C++里面必須有的(JNIEnv代表指向JVM的指針,jclass是調(diào)用該方法的java對(duì)象)策泣,第三個(gè)jobject就是我們java類的方法里面的參數(shù)Object衙傀。注意,這是java函數(shù)與C++函數(shù)對(duì)應(yīng)的靜態(tài)注冊(cè)方法萨咕,即通過(guò)特定的規(guī)則來(lái)寫(xiě)统抬。此處方法名可以隨意起名字,然后還可以用動(dòng)態(tài)注冊(cè)的方式關(guān)聯(lián)兩個(gè)方法任洞。

(3) 創(chuàng)建C或C++文件:在jni文件夾下蓄喇,新建一個(gè).c(c語(yǔ)言)或者.cpp(C++)的文件,來(lái)實(shí)現(xiàn).h文件里聲明的方法:把.h文件里面聲明的方法拷貝到新建的c文件里面交掏,然后在文件里面引入.h文件妆偏,如下圖:

至此,.h文件和c++文件已完成盅弛,想生成so文件還需要在這個(gè)jni目錄下增加兩個(gè)文件钱骂,Android.mk和Application.mk。

注意LOCAL_MODULE的值與之前的java類中設(shè)置要生成so庫(kù)的名字相對(duì)應(yīng)挪鹏,LOCAL_SRC_FILES的值寫(xiě)C++文件的名字见秽,這兩個(gè)值成對(duì)設(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)

// 指定編譯出的庫(kù)類型,BUILD_SHARED_LIBRARY:動(dòng)態(tài)庫(kù)返顺;BUILD_STATIC_LIBRARY:靜態(tài)庫(kù)禀苦, BUILD_EXECUTEABLE指:可執(zhí)行文件

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

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遂鹊,APP_ABI有四種類型(默認(rèn)armeabi)振乏,armeabi、armeabi-v7a秉扑、x86慧邮、mips,設(shè)置時(shí)以空格隔開(kāi),all表示所有误澳。該文件中有個(gè)可選配置的APP_MODULES,類似于上面Android.mk文件中的LOCAL_MODUEL,以空格隔開(kāi)耻矮,且會(huì)覆蓋掉Android.mk文件中的LOCAL_MODULE設(shè)置(比如Android.mk文件中的寫(xiě)了兩個(gè)jni庫(kù)的配置,LOCAL_MODULE:=JNI1脓匿、LOCAL_MODULE:=JNI2,而Application.mk中設(shè)置的APP_MODULES:=JNI1,則只能生成JNI1的so文件淘钟,要生成JNI2的so文件的時(shí)候會(huì)報(bào)錯(cuò),除非寫(xiě)成APP_MODULE:=JNI1 JNI2,這里我們直接省略默認(rèn)使用Android.mk中的)

APP_ABI := all,生成so文件對(duì)C++文件執(zhí)行ndk-build操作陪毡,生成相應(yīng)的so文件

如圖米母,在main/libs目錄下生成了多個(gè)so文件,名字為lib+我們指定的庫(kù)名(同時(shí)還生成了obj文件夾毡琉,中間文件)铁瞒。這時(shí)候我們可以生成的main/libs文件夾內(nèi)的東西復(fù)制到app/libs下,并刪除main下新生成的jni桅滋、libs慧耍、obj三個(gè)文件夾。

配置app/gradle:

調(diào)用在Activity中測(cè)試調(diào)用丐谋,在TextView上顯示我們通過(guò)C++代碼實(shí)現(xiàn)的方法getStrFromC獲取字符串芍碧。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如有侵權(quán),請(qǐng)及時(shí)于我聯(lián)系

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末号俐,一起剝皮案震驚了整個(gè)濱河市泌豆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吏饿,老刑警劉巖踪危,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異猪落,居然都是意外死亡贞远,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)笨忌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蓝仲,“玉大人,你說(shuō)我怎么就攤上這事官疲≡忧” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵袁余,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我咱揍,道長(zhǎng)颖榜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮掩完,結(jié)果婚禮上噪漾,老公的妹妹穿的比我還像新娘。我一直安慰自己且蓬,他們只是感情好欣硼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著恶阴,像睡著了一般诈胜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冯事,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天焦匈,我揣著相機(jī)與錄音,去河邊找鬼昵仅。 笑死缓熟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的摔笤。 我是一名探鬼主播够滑,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吕世!你這毒婦竟也來(lái)了彰触?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寞冯,失蹤者是張志新(化名)和其女友劉穎渴析,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吮龄,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俭茧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漓帚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片母债。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖尝抖,靈堂內(nèi)的尸體忽然破棺而出毡们,到底是詐尸還是另有隱情,我是刑警寧澤昧辽,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布衙熔,位于F島的核電站,受9級(jí)特大地震影響搅荞,放射性物質(zhì)發(fā)生泄漏红氯。R本人自食惡果不足惜框咙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痢甘。 院中可真熱鬧喇嘱,春花似錦、人聲如沸塞栅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)放椰。三九已至作烟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庄敛,已是汗流浹背俗壹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留藻烤,地道東北人绷雏。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像怖亭,于是被迫代替她去往敵國(guó)和親涎显。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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