項目中的公共代碼或者公用模塊,常常使用庫的方式進行管理,除了第三方庫以外,開發中也常常自己定義一個庫。
在Android Studio使用Modules
的方式讓一個庫的源代碼在多個項目中使用,這是gradle在管理Android項目中常用的方式之一,那NDK的library庫又是如何管理的呢?
gradle-experimental
既然是gradle的擴展插件,必然有很多的地方和gradle類似,管理類庫也是采用類似的方式。
新建JNI類庫
當前的gradle-experimental
還不支持直接新建jni module,因此需要需要手動的去新建JNI類庫。
首先把項目從Android
切換到Project
:
這樣項目文件就顯示為了樹狀結構:
新建目錄jni-lib
,在這個目錄下面新建文件bulid.gradle
,這樣jni-lib
目錄就是一個gradle的module了。
在sttings.grable
中把jni-lib,include進來
include
:jni-lib
接下來就需要構建一個基于gradle-experimental
的NDK的 module了。
com.android.model.native
插件com.android.model.native
類似與com.android.library
,是用來構建一個NDK類庫的DSL。
在./jni-lib/build.gradle
中添加代碼:
apply plugin: 'com.android.model.native'
model {
android {
compileSdkVersion = 23
buildToolsVersion = '23.0.2'
defaultConfig {
minSdkVersion.apiLevel = 14
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = '1.0'
}
ndk {
moduleName = 'lib'
abiFilters.addAll(['armeabi', 'armeabi-v7a']) //this is default
ldLibs.addAll(['android', 'log'])
}
}
model.android.ndk
中定義ndk的屬性:
model {
android {
ndk {
moduleName = 'jni-lib'
abiFilters.addAll(['armeabi', 'armeabi-v7a'])
ldLibs.addAll(['log'])
}
}
}
這里定義了類庫的名字為:jni-lib,支持的平臺armeabi
和armeabi-v7a
,調用系統的log庫。
JNI代碼
JNI代碼默認放在module的主目錄下的./src/main/jni
中,按照這個結構新建JNI代碼目錄。
JNI的庫中需要定義.h文件,方便其他module直接引用,在./src/main/jni
中新建llib.h文件
#include <android/log.h>
#define LOG_TAG "jni-lib"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
extern void callMethodFromJniLib();
新建llib.c文件實現llib.h中定義的方法:
#include "llib.h"
extern void callMethodFromJniLib() {
LOGD("call methon from jni lib");
}
引入jni-lib
調用jni-lib類庫的時候,首先需要把header
文件都給暴露出來,這樣可以在其他的module中直接引用,modle.android.sources
中指定需要暴露的文件:
model {
android {
....
sources {
main {
jni {
exportedHeaders {
srcDir "src/main/jni"
}
}
}
}
}
}
通過exportedHeaders
這個DSL就可以塊中指定需要暴露的文件。
其他module中引用jni-lib
的就比較簡單一些了,直接指定jni
的依賴項即可,在model.android.sources.main.jni
中指定依賴:
model {
....
android {
...
sources {
main {
jni {
dependencies{
library 'openssl' linkage 'static'
project ':jni-lib'
}
}
}
}
...
}
}
jni.dependencies
中指定了依賴project:jni-lib,linkage
的默認值為shared
。
這樣就可以在app的jni中直接使用jni-lib中定義的方法了
#include <llib.h>
JNIEXPORT void JNICALL
Java_com_jjz_NativeUtil_callLogFromJni(JNIEnv *env, jclass type) {
callMethodFromJniLib();//jni-lib中的方法
__android_log_print(ANDROID_LOG_INFO, "jni-log", "from jni log");
LOGW("log from define");
}
源代碼地址:https://github.com/jjz/android/tree/master/experimental