開發(fā)環(huán)境信息
列舉下本篇文章編寫的Demo基本信息
| 操作系統(tǒng) | Windows 10 家庭中文版 |
|---|---|
| 開發(fā)工具 | Android Studio 2.1 |
| SDK | new |
| NDK | new |
掃盲之SDK、JDK、NDK的區(qū)別
| SDK | 軟件開發(fā)工具包;英語(yǔ)全稱:Software Development Kit |
|---|---|
| JDK | Java語(yǔ)言的軟件開發(fā)工具包;英語(yǔ)全稱:Java Development Kit |
| NDK | 原生軟件開發(fā)工具包;英語(yǔ)全稱:Native Development Kit;被Google稱為NDK |
由此可見,其實(shí)不管什么XDK,都可以叫SDK,可能為了有很好的區(qū)分,便有了JDK、NDK,所以我們有的時(shí)候常說的SDK并不是特指安卓開發(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)熟門熟路了,如果你還不知道使用Android Studio,我只能說你太不open了。
配置工程N(yùn)DK有兩種方法,和配置SDK一模一樣,這里就說說兩個(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
編寫帶有Native方法的類
1.創(chuàng)建JniDemoClass文件并創(chuàng)建一個(gè)native方法public native String getHelloWordText(),用來獲取Hello Word文本
public class JniDemo {
public native String getHelloWordText();
}
編譯含有Native方法的類
javac JniDemo.java
得到JniDemo.class文件后繼續(xù)用javah命令編譯JniDemo.class,格式:javah package name + class name,示例:
javah com.jay.ndkdemo.JniDemo
其中com.jay.ndkdemo是此類所在的包名,編譯成功會(huì)在當(dāng)前目錄生成一個(gè)*.h文件,這種文件類是C或C++所支持的頭文件類型。內(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
本文示例生成的名稱叫:com_jay_ndkdemo_JniDemo.h,很明顯,以包名+類名生成一個(gè)文件名,我們?cè)诠こ讨袆?chuàng)建一個(gè)文件夾jni,此目錄與工程中的java目錄同級(jí),并把生成的*.h文件放置到jni文件夾中。

編寫C/C++代碼并實(shí)現(xiàn)*.h中聲明的方法
創(chuàng)建*.c<C>或*.cpp<C++>文件,編寫Code,本文編寫的是*.c文件,也就是采用C語(yǔ)法來實(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)單說下編寫方法:
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,這次編譯成功并沒錯(cuò)誤也沒警告,終于NDK編譯通過了,我們查看編譯結(jié)果:\NdkDemo\app\build\intermediates\ndk

我們可以看到,生成了一系列的*.so文件,是不是感覺很熟悉了?但我們發(fā)現(xiàn)*.so文件名叫libapp.so,這個(gè)文件名是怎么來的了?可以更改嗎?答案是肯定的。
先說說默認(rèn)文件名的生成格式:lib + module name.so
更改默認(rèn)文件名名稱:
android {
......
defaultConfig {
......
ndk {
moduleName 'jnidemo'//自定義名稱
}
}
}
好,我們?cè)俅尉幾g,編譯完成后我們查看編譯路徑下,悶B了吧,沒看到ndk目錄了,有人就會(huì)說了,你這個(gè)坑貨,騙人的,友誼的小船說翻就翻。
sourceSets {
main {
// jni.srcDirs=[]
jniLibs.srcDir 'src/main/jni_src'//告知jni源碼目錄
}
}
還記得這個(gè)配置不,對(duì),就是我們之前第一次編譯的時(shí)候解決一個(gè)警告按照警告的推薦寫的配置代碼,只要改成和上面一樣,編譯后就又可以看到編譯目錄下的ndk文件夾了,查看編譯后的*.so文件,發(fā)現(xiàn)文件名已經(jīng)改了,并且生成的格式和我之前說的一樣。
為什么我們按照推薦方法會(huì)有問題了?
1.可能是bug
2.我覺得應(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 ?
