開發(fā)環(huán)境搭建
- Windows下Eclipse+NDK+Cygwin方式:NDK r7之前的版本,必須要安裝Cygwin才能使用NDK姐刁。而在NDKr7開始芥牌,Google簡化了這個(gè)過程,在Eclispe中為NDK提供了一個(gè)ndk-build.cmd的腳本聂使,就可以直接利用這個(gè)腳本編譯壁拉,而不用再安裝Cygwin(Cygwin的作用就是在Windows下模擬Linux環(huán)境)了。只需要為Eclipse Android工程添加一個(gè)Builders柏靶,而為Eclipse配置的builder弃理,其實(shí)就是在執(zhí)行Cygwin,然后傳遞ndk-build作為參數(shù)屎蜓,這樣就能讓Eclipse自動(dòng)編譯NDK了痘昌,這就簡化了我們的開發(fā)流程。
- Windows下eclipse+NDKBundle+Ant:Windows下Eclipse使用ndk-build方式構(gòu)建NDK開發(fā)環(huán)境
- Android Studio 2.3+CMake(AS NDK開發(fā)默認(rèn)的編譯腳本)方式
不得不感慨下炬转,Google對NDK的支持越來越好辆苔,到上面提到的第三種方式時(shí),NDK的開發(fā)扼劈,已經(jīng)不需要你在環(huán)境方面麻煩了驻啤。使用CMake方式創(chuàng)建的支持DNK的項(xiàng)目大概長這樣
這樣方式下,在JNICall中新建一個(gè)本地方法然后“Make Project”测僵,Gradle自動(dòng)會(huì)使用CMake腳本創(chuàng)建本地方法對應(yīng)的頭文件到native-lib.cpp文件中街佑。這樣就可以將更多注意力放在業(yè)務(wù)相關(guān)的C/C++開發(fā)上面。
ndk-build腳本方式下通用開發(fā)流程
- 在類中定義native方法
public class JNIUnit {
public static native String getStringFormC();
}
- 使用javac命令或者AS的編譯工程捍靠,生成.class文件
- 使用javah命令將生成.class文件 --> .h頭文件
cd class文件所在目錄
javah -jni 包名.類名(如com.ns.jnistudy.JNICall)
生成文件 com_ns_jnistudy_JNICall.h如下
/* DO NOT EDIT THIS FILE - it is machine generated */
_#include <jni.h>
...
extern "C" {
//注意到函數(shù)名完全按照:java_pacakege_class_mathod 形式來命名沐旨。
//Class: com_example_hellojni_HelloJni
//Method: stringFromJNI
//Signature: ()Ljava/lang/String;
JNIEXPORT jstring JNICALL Java_com_ns_jnistudy_JNICall_getStringFormC
(JNIEnv *, jobject);
...
}
...
- 將上述文件移動(dòng)到的項(xiàng)目的jni目錄下并實(shí)現(xiàn).h文件對應(yīng)的.c文件
JNIEXPORT jstring JNICALL Java_com_ns_jnistudy_JNICall_getStringFormC
(JNIEnv *, jobject){
return (*env)->NewStringUTF(env,"just have a test");
}
- 在jni目錄下增加Android.mk和Application.mk文件,關(guān)于這兩個(gè)文件的含義以及如何配置參見NDK編程--鳥瞰榨婆。
- 環(huán)境配置
在 file ->project structure 中增加 ndk的路徑磁携,或者在local.properties 中增加ndk路徑。在 gradle.preperties 中增加android.useDeprecatedNdk=true
修改build.gradle在 defaultConfig 節(jié)增加如下配置
ndk {
moduleName "NdkJniDemo" //生成的so庫的名字
abiFilters "armeabi", "armeabi-v7a", "x86"http://ABI平臺(tái)
}
配置完成之后良风,當(dāng)程序構(gòu)建時(shí)谊迄,Gradle(一種自動(dòng)化構(gòu)建工具,如完成編譯烟央,打包统诺,測試等功能)so文件打包進(jìn)APK中。 - cd到ndk目錄下執(zhí)行ndk-build命令(ndk-build把.c文件編譯疑俭,鏈接生成各平臺(tái)對應(yīng)的.so文件)
- 在程序的入口處(Application或者M(jìn)ainActivity或定義本地方法的類中)
static {
System.loadLibrary("so庫名字");
}
注意:第3步與第6步使用了javah和ndk-build命令粮呢,可以將命令配置成eclipse工具或將命令配置成Android Studio工具。
運(yùn)行時(shí)Java通過JNI調(diào)用流程
- 當(dāng)本地放在所在的類被第一次加載的時(shí)候钞艇,靜態(tài)代碼塊會(huì)先行加載啄寡。
- 調(diào)用的時(shí)候通過本地方法調(diào)用so文件的C/C++實(shí)現(xiàn)
關(guān)于ndk-build與cmake:
NDK本身是用來Android下編譯C/C++代碼的一個(gè)編譯器和庫的集合。這兩個(gè)家伙都是基于NDK的編譯系統(tǒng)(編譯腳本)哩照,使用項(xiàng)目里的Java代碼挺物,將本地代碼編譯到共享庫中,兩個(gè)門干的事同一件事飘弧,解決的是同一個(gè)問題识藤。ndk-build是NDK的包含的編譯系統(tǒng),使用Android.mk眯牧;cmake使用CMakeLists.txt蹋岩,在你的Module app的build.gradle中你可以看到這句話
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
那有哥們或者妹子就不同意了,既然都一樣学少,該如何選呢剪个?ok,這問題Google已經(jīng)幫我們做選擇了版确,AS默認(rèn)是支持CMake扣囊。且CMake腳本在非Android開發(fā)者中很流行。CMake的主要便利在于你可以使用一套編譯文件構(gòu)建所有的目標(biāo)平臺(tái)(Android绒疗,Linux侵歇,Windows,IOS吓蘑,etc)惕虑。
但是Google幫我們做了很多開發(fā)效率上的改進(jìn)坟冲,但是們?nèi)孕枰繢NK開發(fā)背后的邏輯,這里以ndk-build腳本的角度來講溃蔫。
參考
NDK Official tutorials
Add C and C++ Code to Your Project
Android NDK--everything you need to know
windows下Eclipse+NDK bundle開發(fā)
windows下Android Studio+NDK bundle開發(fā)