Android JNI/NDK開(kāi)發(fā)之基本姿勢(shì)<一>

開(kāi)發(fā)環(huán)境信息

列舉下本篇文章編寫(xiě)的Demo基本信息
操作系統(tǒng) Windows 10 家庭中文版
開(kāi)發(fā)工具 Android Studio 2.1
SDK new
NDK new

掃盲之SDK乳丰、JDK、NDK的區(qū)別

SDK 軟件開(kāi)發(fā)工具包内贮;英語(yǔ)全稱(chēng):Software Development Kit
JDK Java語(yǔ)言的軟件開(kāi)發(fā)工具包产园;英語(yǔ)全稱(chēng):Java Development Kit
NDK 原生軟件開(kāi)發(fā)工具包;英語(yǔ)全稱(chēng):Native Development Kit夜郁;被Google稱(chēng)為NDK

由此可見(jiàn)什燕,其實(shí)不管什么XDK,都可以叫SDK竞端,可能為了有很好的區(qū)分屎即,便有了JDKNDK事富,所以我們有的時(shí)候常說(shuō)的SDK并不是特指安卓開(kāi)發(fā)工具包技俐,而只是我們都是同行,交流的時(shí)候都知道指的是什么统台,其實(shí)你們會(huì)發(fā)現(xiàn)雕擂,我們常常接三方平臺(tái)的時(shí)候,那些工具包也是叫SDK贱勃,但可能我們?cè)诮涣鞯臅r(shí)候就會(huì)加個(gè)前綴井赌,比如:微信分享SDK、支付寶SDK贵扰、xxSDK仇穗。


學(xué)習(xí)目標(biāo)

1.配置NDK環(huán)境并學(xué)會(huì)合理利用Android Studio工具進(jìn)行NDK的編譯
2.點(diǎn)擊某個(gè)按鈕顯示由native方法返回的一段文本信息;java > native
3.點(diǎn)擊某個(gè)按鈕調(diào)用某個(gè)native方法戚绕,在由此native方法調(diào)用java方法仪缸;java > native > java

創(chuàng)建工程并配置NDK路徑

快速利用Android Studio創(chuàng)建一個(gè)簡(jiǎn)單的Hello Word工程,相信這個(gè)大家都已經(jīng)熟門(mén)熟路了列肢,如果你還不知道使用Android Studio,我只能說(shuō)你太不open了宾茂。

配置工程N(yùn)DK有兩種方法瓷马,和配置SDK一模一樣,這里就說(shuō)說(shuō)兩個(gè)SDK [1] 的配置方法吧

1.直接在local.properties文件中手動(dòng)配置

ndk.dir=E:\Android\sdk\ndk-bundle //NDK路徑
sdk.dir=E:\Android\sdk //SDK路徑

2.Open Module Settings

選中工程名跨晴,鼠標(biāo)右鍵>Open Module Settings或直接按下F4功能鍵


sdk.dir

編寫(xiě)帶有Native方法的類(lèi)

1.創(chuàng)建JniDemoClass文件并創(chuàng)建一個(gè)native方法public native String getHelloWordText()欧聘,用來(lái)獲取Hello Word文本

public class JniDemo {

    public native String getHelloWordText();
    
}

編譯含有Native方法的類(lèi)

javac JniDemo.java

得到JniDemo.class文件后繼續(xù)用javah命令編譯JniDemo.class,格式:javah package name + class name端盆,示例:

javah com.jay.ndkdemo.JniDemo

其中com.jay.ndkdemo是此類(lèi)所在的包名怀骤,編譯成功會(huì)在當(dāng)前目錄生成一個(gè)*.h文件费封,這種文件類(lèi)是C或C++所支持的頭文件類(lèi)型。內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jay_ndkdemo_JniDemo */

#ifndef _Included_com_jay_ndkdemo_JniDemo
#define _Included_com_jay_ndkdemo_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jay_ndkdemo_JniDemo
 * Method:    getHelloWordText
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jay_ndkdemo_JniDemo_getHelloWordText
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

本文示例生成的名稱(chēng)叫:com_jay_ndkdemo_JniDemo.h蒋伦,很明顯弓摘,以包名+類(lèi)名生成一個(gè)文件名,我們?cè)诠こ讨袆?chuàng)建一個(gè)文件夾jni痕届,此目錄與工程中的java目錄同級(jí)韧献,并把生成的*.h文件放置到jni文件夾中。

jni


編寫(xiě)C/C++代碼并實(shí)現(xiàn)*.h中聲明的方法

創(chuàng)建*.c<C>*.cpp<C++>文件研叫,編寫(xiě)Code,本文編寫(xiě)的是*.c文件锤窑,也就是采用C語(yǔ)法來(lái)實(shí)現(xiàn)

#include <com_jay_ndkdemo_JniDemo.h>

/*
 * Class:     com_jay_ndkdemo_JniDemo
 * Method:    getHelloWordText
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jay_ndkdemo_JniDemo_getHelloWordText
  (JNIEnv * env, jobject obj)
{
 return (*env)->NewStringUTF(env,"Hello Word From Jni");
}

簡(jiǎn)單說(shuō)下編寫(xiě)方法:
1.include 下我們前面生成的*.h文件
2.實(shí)現(xiàn)*.h中未實(shí)現(xiàn)的方法,注意方法名要與*.h中保持一致

到這里嚷炉,我們的工作已經(jīng)完成了90%渊啰,剩下的只是配置與調(diào)用了


NDK編譯

這個(gè)時(shí)候我們就要發(fā)揮Android Studio工具的方便性了,怎么利用NDK編譯了申屹?前面我們已經(jīng)配置好了NDK路徑绘证,那么直接利用Android Studio的菜單build > Rebuild Project,執(zhí)行后發(fā)現(xiàn)失敗

ndk-build-error

錯(cuò)誤信息:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugNdk'.
> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

其實(shí)這個(gè)錯(cuò)誤信息中已經(jīng)告訴我們?cè)趺唇鉀Q

Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration

叫我們?cè)?code>gradle.properties文件中輸入android.useDeprecatedNdk=true独柑,輸入后我們?cè)俅尉幾g迈窟,這次編譯成功,但發(fā)現(xiàn)一個(gè)警告:

ndk-build-warning

警告信息:

Warning: Native C/C++ source code is found, but it seems that NDK option is not configured.  Note that if you have an Android.mk, it is not used for compilation.  The recommended workaround is to remove the default jni source code directory by adding: 
 android {
    sourceSets {
        main {
            jni.srcDirs = []
        }
    }
}
to build.gradle, manually compile the code with ndk-build, and then place the resulting shared object in src/main/jniLibs.

大概意思就是我們?nèi)鄙僖粋€(gè)文件:Android.mk忌栅,但人家給了我們推薦的方法车酣,那就是在對(duì)應(yīng)module工程中的build.gradle文件中添加如下代碼:

sourceSets {
    main {
        jni.srcDirs = []
    }
}

添加后我們?cè)俅尉幾g,這次編譯成功并沒(méi)錯(cuò)誤也沒(méi)警告索绪,終于NDK編譯通過(guò)了湖员,我們查看編譯結(jié)果:\NdkDemo\app\build\intermediates\ndk

ndk-build-result

我們可以看到,生成了一系列的*.so文件瑞驱,是不是感覺(jué)很熟悉了娘摔?但我們發(fā)現(xiàn)*.so文件名叫libapp.so,這個(gè)文件名是怎么來(lái)的了唤反?可以更改嗎凳寺?答案是肯定的。

先說(shuō)說(shuō)默認(rèn)文件名的生成格式:lib + module name.so

更改默認(rèn)文件名名稱(chēng):

android {
    ......
    defaultConfig {
        ......
        ndk {
            moduleName 'jnidemo'//自定義名稱(chēng)
        }
    }
}

好彤侍,我們?cè)俅尉幾g肠缨,編譯完成后我們查看編譯路徑下,悶B了吧盏阶,沒(méi)看到ndk目錄了晒奕,有人就會(huì)說(shuō)了,你這個(gè)坑貨,騙人的脑慧,友誼的小船說(shuō)翻就翻魄眉。

sourceSets {
    main {
//      jni.srcDirs=[]
      jniLibs.srcDir 'src/main/jni_src'//告知jni源碼目錄
    }
}

還記得這個(gè)配置不,對(duì)闷袒,就是我們之前第一次編譯的時(shí)候解決一個(gè)警告按照警告的推薦寫(xiě)的配置代碼坑律,只要改成和上面一樣,編譯后就又可以看到編譯目錄下的ndk文件夾了霜运,查看編譯后的*.so文件脾歇,發(fā)現(xiàn)文件名已經(jīng)改了,并且生成的格式和我之前說(shuō)的一樣淘捡。

為什么我們按照推薦方法會(huì)有問(wèn)題了藕各?
1.可能是bug
2.我覺(jué)得應(yīng)該是我們既然了默認(rèn)的一些參數(shù),當(dāng)然就要對(duì)其它參數(shù)做出相應(yīng)的修改


好了焦除,看完這篇文章激况,我們基本實(shí)現(xiàn)了我們的學(xué)習(xí)目標(biāo)的第一點(diǎn),后面兩點(diǎn)請(qǐng)看后續(xù)系列文章


  1. 此處SDK包含NDK與安卓SDK ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膘魄,一起剝皮案震驚了整個(gè)濱河市乌逐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌创葡,老刑警劉巖浙踢,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異灿渴,居然都是意外死亡洛波,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)骚露,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蹬挤,“玉大人,你說(shuō)我怎么就攤上這事棘幸⊙姘猓” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵误续,是天一觀的道長(zhǎng)吨悍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蹋嵌,這世上最難降的妖魔是什么育瓜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮欣尼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己愕鼓,他們只是感情好钙态,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著菇晃,像睡著了一般册倒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磺送,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天驻子,我揣著相機(jī)與錄音,去河邊找鬼估灿。 笑死崇呵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的馅袁。 我是一名探鬼主播域慷,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼汗销!你這毒婦竟也來(lái)了犹褒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤弛针,失蹤者是張志新(化名)和其女友劉穎叠骑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體削茁,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宙枷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了付材。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朦拖。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厌衔,靈堂內(nèi)的尸體忽然破棺而出璧帝,到底是詐尸還是另有隱情,我是刑警寧澤富寿,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布睬隶,位于F島的核電站,受9級(jí)特大地震影響页徐,放射性物質(zhì)發(fā)生泄漏苏潜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一变勇、第九天 我趴在偏房一處隱蔽的房頂上張望恤左。 院中可真熱鬧贴唇,春花似錦、人聲如沸飞袋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)巧鸭。三九已至瓶您,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纲仍,已是汗流浹背呀袱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留郑叠,地道東北人夜赵。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像锻拘,于是被迫代替她去往敵國(guó)和親油吭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,078評(píng)論 25 707
  • Android游戲開(kāi)發(fā)實(shí)踐(1)之NDK與JNI開(kāi)發(fā)02 承接上篇Android游戲開(kāi)發(fā)實(shí)踐(1)之NDK與JNI...
    AlphaGL閱讀 3,750評(píng)論 0 24
  • 一署拟、NDK產(chǎn)生的背景 Android平臺(tái)從誕生起婉宰,就已經(jīng)支持C、C++開(kāi)發(fā)推穷。眾所周知心包,Android的SDK基于J...
    Ten_Minutes閱讀 3,502評(píng)論 1 27
  • LZ-Says:半夜睡覺(jué)滾了地上了,無(wú)奈之下醒來(lái)了馒铃,想想最近幾天因?yàn)橐粋€(gè)括號(hào)導(dǎo)致JNI遲遲不能開(kāi)展蟹腾,心里面無(wú)奈又崩...
    靜心Study閱讀 2,055評(píng)論 0 6
  • 原本約同學(xué)周四見(jiàn)面的,今天接到同學(xué)電話(huà)因?yàn)榧依餇t子壞了区宇,改在下周見(jiàn)面娃殖。 公司開(kāi)會(huì)一天就忙活公司的事了。 晚上和客戶(hù)...
    唐豆閱讀 111評(píng)論 0 0