專案中的公共程式碼或者公用模組,常常使用庫的方式進行管理,除了第三方庫以外,開發中也常常自己定義一個庫。
在Android Studio使用Modules的方式讓一個庫的原始碼在多個專案中使用,這是gradle在管理Android專案中常用的方式之一,那NDK的library庫又是如何管理的呢?
gradle-experimental既然是gradle的擴充套件外掛,必然有很多的地方和gradle類似,管理類庫也是採用類似的方式。
新建JNI類庫
當前的gradle-experimental還不支援直接新建jni module,因此需要需要手動的去新建JNI類庫。
首先把專案從Android切換到Project:
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中新增程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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的屬性:
1 2 3 4 5 6 7 8 9 |
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檔案
1 2 3 4 5 6 |
#include #define LOG_TAG "jni-lib" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) extern void callMethodFromJniLib(); |
新建llib.c檔案實現llib.h中定義的方法:
1 2 3 4 5 |
#include "llib.h" extern void callMethodFromJniLib() { LOGD("call methon from jni lib"); } |
引入jni-lib
呼叫jni-lib類庫的時候,首先需要把header檔案都給暴露出來,這樣可以在其他的module中直接引用,modle.android.sources中指定需要暴露的檔案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
model { android { .... sources { main { jni { exportedHeaders { srcDir "src/main/jni" } } } } } } |
通過exportedHeaders這個DSL就可以塊中指定需要暴露的檔案。
其他module中引用jni-lib的就比較簡單一些了,直接指定jni的依賴項即可,在model.android.sources.main.jni中指定依賴:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
model { .... android { ... sources { main { jni { dependencies{ library 'openssl' linkage 'static' project ':jni-lib' } } } } ... } } |
jni.dependencies中指定了依賴project:jni-lib,linkage的預設值為shared。
這樣就可以在app的jni中直接使用jni-lib中定義的方法了
1 2 3 4 5 6 7 8 9 |
#include 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