2014年中的時(shí)候,當(dāng)時(shí)國(guó)內(nèi)使用 Android Studio 的人還沒有很多,很多人還沒處理嘗鮮的時(shí)候我開始把公司的項(xiàng)目遷移到 Android Studio 上了,開始了挺長(zhǎng)一段踩坑的日子,開始接觸到了 Gradle,才開始了解到使用它來(lái)管理項(xiàng)目的依賴庫(kù),由于在過(guò)程中有不少第三方庫(kù)是沒有將依賴包發(fā)布到 jCenter / Maven Central ,而且個(gè)人并不太喜歡把一整個(gè)開源項(xiàng)目添加到項(xiàng)目中,導(dǎo)致經(jīng)常使用一些非官方倉(cāng)庫(kù),從而可能給后續(xù)維護(hù)帶來(lái)一些問題。
例如:
- 依賴庫(kù)可能有被做修改導(dǎo)致產(chǎn)生不必要的 Bug
- 依賴庫(kù)被作者從倉(cāng)庫(kù)中刪掉
- 依賴庫(kù)更新不及時(shí),升級(jí)依賴庫(kù)麻煩
- 后續(xù)跟進(jìn)的開發(fā)者無(wú)法得知依賴庫(kù)的來(lái)源
- 等等一系統(tǒng)問題~
不地可以通過(guò)以下兩個(gè)解決方案解決:
- 給作者提 issues 讓作者將庫(kù)提交到 jCenter / Maven Central
- 自己 fork 一份代碼后提交到 JitPack 上
其實(shí)在過(guò)程中一真會(huì)出現(xiàn)一些倉(cāng)庫(kù)地址的 URL 是 GitHub 的地址。
例如 Emojicon 庫(kù),現(xiàn)在最新版本已經(jīng)發(fā)布到 jCenter 了:
build.gradle
...
allprojects {
repositories {
maven { url 'https://raw.githubusercontent.com/rockerhieu/mvn-repo/master/' }
jcenter()
}
}
...
app/build.gradle
...
dependencies {
...
compile 'com.rockerhieu.emojicon:library:1.2'
}
最終定位到了這個(gè)倉(cāng)庫(kù) https://github.com/Goddchen/mvn-repo,后來(lái)對(duì)此進(jìn)行了一些研究,了解到如何使用公共的 Git 倉(cāng)庫(kù)發(fā)布依賴庫(kù),后面我就把一些常用的庫(kù)自己編譯發(fā)布到自己的 GitHub 的 mvn-repo 倉(cāng)庫(kù)上,同樣達(dá)到了相同的效果,并且更可控。
發(fā)布一個(gè)依賴庫(kù)到 mvn-repo
在 GitHub 創(chuàng)建 mvn-repo 倉(cāng)庫(kù)
這一步就不詳述了,相信大家 Git 和 GitHub 使用肯定比我還熟練。
創(chuàng)建一個(gè)新的 Android Library 項(xiàng)目
由于本人已經(jīng)不使用 Eclipse,所以肯定是使用 Android Studio。
創(chuàng)建一個(gè) BlankApp 項(xiàng)目,這個(gè)項(xiàng)目是自己在開發(fā)過(guò)程中為了優(yōu)化開發(fā)流程而寫的(之前的版本 被廢棄了,這個(gè)是重寫版,還在構(gòu)思中)
這是目錄結(jié)構(gòu)
.
├── BlankApp.iml
├── LICENSE
├── README.md
├── build
│ ├── generated
│ └── intermediates
├── build.gradle
├── examples
│ ├── build
│ ├── build.gradle
│ ├── examples.iml
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
├── gradle
│ └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── library
│ ├── build
│ ├── build.gradle
│ ├── gradle.properties
│ ├── library.iml
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
├── local.properties
└── settings.gradle
library 就是一個(gè) Android Library 的Module,examples 是一個(gè)Demo Module。
使用 gradle-mvn-push 編譯腳本
使用了Chris Banes 大神開發(fā)的 gradle-mvn-push Gradle 腳本,Chris Banes大神是 Android-PullToRefresh、PhotoView 等流行開源庫(kù)的作者。
在項(xiàng)目根目錄創(chuàng)建 gradle.properties 文件
COMPILE_SDK_VERSION=23
BUILD_TOOLS_VERSION=23.0.2
MIN_SDK_VERSION=14
TARGET_SDK_VERSION=23
VERSION_NAME=0.0.1-alpha
VERSION_CODE=1
GROUP=org.blankapp
POM_DESCRIPTION=
POM_URL=https://github.com/lijy91/BlankApp
POM_SCM_URL=https://github.com/lijy91/BlankApp
POM_SCM_CONNECTION=scm:git@github.com:lijy91/BlankApp.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:lijy91/BlankApp.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=lijy91
POM_DEVELOPER_NAME=JianyingLi <lijy91@foxmail.com>
RELEASE_REPOSITORY_URL=file:///Users/Lijy91/Documents/Projects/mvn-repo/
SNAPSHOT_REPOSITORY_URL=file:///Users/Lijy91/Documents/Projects/mvn-repo/snapshots/
RELEASE_REPOSITORY_URL 和 SNAPSHOT_REPOSITORY_URL 兩個(gè)配置分別是正式版和快照版的本地路徑。如果版本號(hào)后帶有 -SNAPSHOT 編譯后會(huì)發(fā)布到 SNAPSHOT_REPOSITORY_URL 相應(yīng)的目錄下。
在 library 創(chuàng)建 gradle.properties 文件
app/library/gradle.properties
POM_NAME=BlankApp Library
POM_ARTIFACT_ID=blankapp
POM_PACKAGING=aar
在 library 模塊調(diào)用 gradle-mvn-push 腳本
library/build.gradle
...
apply from: 'https://raw.githubusercontent.com/lijy91/gradle-mvn-push/master/gradle-mvn-push.gradle'
加在文件的未行即可,然后執(zhí)行 Sync Now 即可
編譯到本地 Git 倉(cāng)庫(kù),并Push到遠(yuǎn)程倉(cāng)庫(kù)
Build
$ ./gradlew clean build uploadArchives
執(zhí)行些命令后,會(huì)在 /Users/Lijy91/Documents/Projects/mvn-repo/ 創(chuàng)建相關(guān)的文件
.
├── README.md
└── org
└── blankapp
├── blankapp
│ ├── 0.0.1-alpha
│ │ ├── blankapp-0.0.1-alpha-javadoc.jar
│ │ ├── blankapp-0.0.1-alpha-javadoc.jar.md5
│ │ ├── blankapp-0.0.1-alpha-javadoc.jar.sha1
│ │ ├── blankapp-0.0.1-alpha-sources.jar
│ │ ├── blankapp-0.0.1-alpha-sources.jar.md5
│ │ ├── blankapp-0.0.1-alpha-sources.jar.sha1
│ │ ├── blankapp-0.0.1-alpha.aar
│ │ ├── blankapp-0.0.1-alpha.aar.md5
│ │ ├── blankapp-0.0.1-alpha.aar.sha1
│ │ ├── blankapp-0.0.1-alpha.pom
│ │ ├── blankapp-0.0.1-alpha.pom.md5
│ │ └── blankapp-0.0.1-alpha.pom.sha1
│ ├── maven-metadata.xml
│ ├── maven-metadata.xml.md5
│ └── maven-metadata.xml.sha1
└── ...
Push
$ git add .
$ git commit -am "Add BlankApp Library"
$ git push -u origin master
到此,一個(gè)私人的Maven倉(cāng)庫(kù)已經(jīng)創(chuàng)建完成
如何使用 mvn-repo
1、只需將 mvn-repo 地址添加到您的 build.gradle 文件:
repositories {
maven { url 'https://raw.githubusercontent.com/lijy91/mvn-repo/master/' }
jcenter()
}
2、在要集成的項(xiàng)目中的 build.gradle 中添加依賴,如下:
dependencies {
compile 'org.blankapp:blankapp:0.0.1-alpha@aar'
}
對(duì)于自己開發(fā)第三方庫(kù)的一些建議
盡量不依賴第三方庫(kù)
我最早寫的一個(gè)基礎(chǔ)框架庫(kù),就引用了一些個(gè)人認(rèn)為比較好用的 JSON 解析庫(kù),ORM庫(kù),后來(lái)應(yīng)用在其他項(xiàng)目的時(shí)候發(fā)現(xiàn)有一些是在這個(gè)項(xiàng)目中是使用不到的,造成了耦合度過(guò)大,后面維護(hù)難度過(guò)大。所以建議盡量不要依賴,或者參考最后面兩個(gè)建議的做法。
ARTIFACT_ID 不要使用 library,sdk等名稱
如果 ArtifactId 使用的是 library,sdk 這種名字,編譯后生成的相關(guān)文件就會(huì)是 library.jar、sdk.jar 這種文件,不便于分辨。
例如 FIR.im 的 SDK
compile 'im.fir:sdk:latest.integration@aar'
最終在 Android Studio 看到的 External Libraries 就會(huì)出現(xiàn)一個(gè)sdk.jar 的文件,如果你引用了多個(gè) ArtifactId 為 library 的類庫(kù),那就會(huì)出現(xiàn) library.jar、library1.jar 這樣的文件,根本無(wú)法分辨。
后來(lái)在我的建議下修改為
compile 'im.fir:fir-sdk:latest.integration@aar'
多模塊
以下是之前我對(duì) Ping++ SDK 提的一些建議
將基礎(chǔ)部分封裝為一個(gè)sdk 模塊,并提供統(tǒng)一的接口,然后支付寶,微信支付,百度錢包等根據(jù)sdk模塊提供的接口進(jìn)行開發(fā),后面如果用戶需要接入或者升級(jí)支付平臺(tái)的內(nèi)容,即可以通過(guò)在 build.gradle 文件添加相應(yīng)平臺(tái)的依賴即可。
在 build.gradle 使用時(shí)類似這樣子
compile 'com.pingxx:pingxx-sdk:1.0.+'
compile 'com.pingxx:pingxx-alipay:1.0.+'
compile 'com.pingxx:pingxx-wxpay:1.0.+'
避免引用后項(xiàng)目出現(xiàn)重復(fù)功能的庫(kù)
這個(gè)問題估計(jì)是大多數(shù)項(xiàng)目都有出現(xiàn)的問題,例如有我的項(xiàng)目使用了 Fastjson 作為我的JSON解析庫(kù),但我使用的HTTP庫(kù) Retrofit 1.x 卻使用 Gson,這個(gè)時(shí)候我的項(xiàng)目里就引用了兩個(gè)同樣功能的庫(kù),而且在我們不注意的時(shí)候,包括HTTP庫(kù),圖片加載庫(kù)等等都有可能會(huì)有重疊,會(huì)大大增加我們APK的大小。
后來(lái)Retrofit2解決了這個(gè)問題,它把數(shù)據(jù)轉(zhuǎn)換為獨(dú)立出來(lái)了,我們可以自由選擇自己的數(shù)據(jù)轉(zhuǎn)換庫(kù),類似這樣
com.squareup.retrofit2:converter-gson // Gson
com.squareup.retrofit2:converter-jackson // Jackson
com.squareup.retrofit2:converter-moshi // Moshi
com.squareup.retrofit2:converter-protobuf // Protobuf
com.squareup.retrofit2:converter-wire // Wire
com.squareup.retrofit2:converter-simplexml // Simple XML
com.squareup.retrofit2:converter-scalars // Scalars (primitives, boxed, and String)
Enjoy~