開(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ū)分屎即,便有了JDK
、NDK
事富,所以我們有的時(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功能鍵
編寫(xiě)帶有Native方法的類(lèi)
1.創(chuàng)建JniDemo
Class文件并創(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
文件夾中。
編寫(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)失敗
錯(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è)警告:
警告信息:
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
我們可以看到,生成了一系列的*.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ù)系列文章
-
此處
SDK
包含NDK與安卓SDK ?