標籤:android so gradle
@author ASCE1885的 Github 簡書 微博 CSDN
原文連結
背景
幾個月前,基於Google的LevelDB,我為Android平台寫了一個名為SnappyDB的索引值資料庫(NoSQL)。
由於它使用到了原生C++代碼,因此最終產生的檔案除了Jars包還有so檔案。
通過Maven倉庫發布我們的函數庫沒有什麼問題(只要你通過繁瑣的發布流程),maven-android-plugin可以協助我們包含共用庫。Maven依賴規則使得我們可以指定想要擷取的ABI(不同的CPU架構)的類型以及函數庫的格式(我們的是.so格式)。
例如,為SnappyDB擷取ARM平台共用庫:
<dependency> <groupId>com.snappydb</groupId> <artifactId>snappydb-native</artifactId> <version>0.2.0</version> <classifier>armeabi</classifier> <type>so</type></dependency>
如果你使用的是Maven+Eclipse ADT來構建你的Android應用,使用這個方法沒有問題,但如果你將工程遷移到Android Studio+Gradle上,問題就來了。
Android Studio & Gradle
Android的Gradle外掛程式能夠很好的處理使用maven倉庫的所有的jars依賴(以及其他)。
例如,在build.gradle檔案中聲明依賴:
dependencies { classpath ‘commons-io:commons-io:2.4‘}
但是當需要依賴原生函數庫時就遇到問題了,類比於Maven,我們不再能夠以下面這種方式來載入了:
dependencies { classpath ‘com.snappydb:snappydb-native:2.+:arm-v7a‘}
這是因為Android Studio外掛程式對於NDK的支援還做不到這一點。
jniLibs拯救了我們
在Android Studio的0.7.2版本的Android外掛程式中,Google在工程的source sets中引入了一個新的目錄‘jniLibs’。這意味著我們可以把預先編譯好的.so檔案拷貝到這個目錄中,之後Android外掛程式就會幫我們將這些原生函數庫打包進APK中。
.├── AndroidManifest.xml└── jniLibs ├── armeabi │ └── libsnappydb-native.so ├── armeabi-v7a │ └── libsnappydb-native.so ├── mips │ └── libsnappydb-native.so └── x86 └── libsnappydb-native.so
這個特性很強大,不過開發人員還是需要下載預先編譯好的.so檔案,並手動拷貝到這個目錄中,當我們使用類似Jenkins或者Travis的持續整合系統時就顯得不完美了。
已經有很多hacks技巧和解決方案嘗試解決這個問題,但很多實際上很繁瑣同時要求使用者手動下載並拷貝這些原生函數庫依賴。
因此,我們需要有更好的解決方案。
android-native-dependencies的引入
android-native-dependencies是我寫的一個自動處理尋找&下載&拷貝原生函數庫依賴到jniLibs目錄的Android外掛程式,這樣在APK構建過程中可以自動包含這些函數庫。
這個外掛程式使用跟聲明尋找jar包一樣的倉庫,下面是一個例子:
buildscript { repositories { mavenCentral() } dependencies { classpath ‘com.android.tools.build:gradle:0.10.+‘ classpath ‘com.nabilhachicha:android-native-dependencies:0.1‘ }}apply plugin: ‘android‘apply plugin: ‘android-native-dependencies‘native_dependencies { artifact ‘com.snappydb:snappydb-native:0.2+:armeabi‘ artifact ‘com.snappydb:snappydb-native:0.2+:x86‘}dependencies { //regular Jar dependencies ...}
規約
DSL artifact遵循Maven artifacts的命名規則。因此,我們下面兩種文法都可以使用:
- group:name:version[:classifier]縮寫
//adding x86 classifier will resolve only intel‘s (.so) libnative_dependencies { artifact ‘com.snappydb:snappydb-native:0.2+:x86‘}//omit the classifier will resolve all supported architecturesnative_dependencies { artifact ‘com.snappydb:snappydb-native:0.2+‘}
//adding x86 classifier will resolve only intel‘s (.so) libnative_dependencies { artifact group: ‘com.snappydb‘, name: ‘snappydb-native‘, version: ‘0.2+‘, classifier: ‘x86‘}//omit the classifier will resolve all supported architecturesnative_dependencies { artifact group: ‘com.snappydb‘, name: ‘snappydb-native‘, version: ‘0.2+‘}
在每種文法中,classifier都是可選的。這意味著,當忽略classifier時,外掛程式將會嘗試擷取所有類型CPU架構(armeabi, armeabi-v7a, x86和mips)的artifacts。
總結
在Android Gradle外掛程式完全支援NDK之前,使用android-native-dependencies可以協助我們構建CI和自動化原生依賴的重複性的任務。
我同時推薦另一個很棒的由Jake Wharton寫的Gradle外掛程式:android-sdk-manager,它可以協助你下載和管理Android SDK。
文末攝影鑒賞
如何在Android Gradle中添加原生so檔案依賴