正確的姿勢來優(yōu)化你的build.gradle

轉自:http://chenzhongjin.cn/2016/06/23/正確的姿勢來優(yōu)化你的build-gradle/

引言

eclipse 已經成功了過去式.人人 Android Studio 時代已經到來.面對 gradle .很多人都誠惶誠恐.甚至很多時候github clone下來的項目都不會編譯.gradle version尔许、gradle plugin version、sdk version、support version 的概念都沒有分清楚.導致因為跟原作者的一些配置和本地擁有的環(huán)境不匹配而無法編譯成功.剛好公司項目到了一個階段性手尾.趁著有一點時間.特地記錄一下.和大家一齊分享交流.

下面統(tǒng)一用我寫的一個RecyclerView的開源項目 RvHelper 來作為sample代碼:RvHelper-github

統(tǒng)一管理所有依賴

在項目中新建一個buildsystem文件夾.并且新建一個dependencies.gradle文件.文件夾名稱和文件名字隨意.自己使用的時候映射即可.如圖:

然后再進行文件的編寫

ext.versions = [
code : 1,
name : '1.0.0',

    minSdk     : 15,
    targetSdk  : 23,
    compileSdk : 23,
    buildTools : '23.0.3',

    // Library versions
    junit      : '4.12',
    supportLibs: '23.4.0',
    multidex   : '1.0.1',

]
ext.libraries = [
junit : "junit:junit:$versions.junit",
supportV4 : "com.android.support:support-v4:$versions.supportLibs",
supportAppCompat : "com.android.support:appcompat-v7:$versions.supportLibs",
supportDesign : "com.android.support:design:$versions.supportLibs",
supportRecyclerView : "com.android.support:recyclerview-v7:$versions.supportLibs",
supportCardView : "com.android.support:cardview-v7:$versions.supportLibs",
supportAnnotations : "com.android.support:support-annotations:$versions.supportLibs",

    //拆dex
    multidex             : "com.android.support:multidex:1.0.1",

]
上面只是提供了最簡單的一些依賴的配置.這樣做的好處就是.如果存在多個module.同時都依賴相同的 minSdk & targetSdk & compileSdk & buildTools & supportLibs 就變得非常的方便.比較好管理.

gradle version說明

首先.對于項目來講.gradle version會在如下的文件里面進行聲明.

可以看到我目前使用的版本是 gradle2.10.當然.其實本身下載Android Studio的時候自帶也有一個默認的Gradle.如圖:

不過如果你想自己想嘗鮮的話.也可以到gradle官網(wǎng)進行下載.

下載好之后配置一下環(huán)境變量即可.
配置好之后也可以在項目中指定gradle文件夾.如圖:

gradle plugin version說明

很多時候.gradle plugin版本和本地的as自帶的版本不對應.然后剛好又被墻了.沒有自備梯子.就導致無法編譯.所以在open project之前對應自己本地as的版本來修改好是很重要的一件事.
首先.打開項目根目錄的 build.gradle 如圖:

類似的.現(xiàn)在我的as版本是 2.1.2.那么.我的gradle plugin version就應該對應就是

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
}
}
如果我的as版本是2.2pv3.那么將會是

classpath 'com.android.tools.build:gradle:2.2-alpha3'
當然其實本身如果你剛好在用as2.2pv3的話.其實你打開項目的時候.他就會機智的彈出讓你升級的選擇框了.

module中使用統(tǒng)一配置

首先需要在根目錄的 build.gradle 中聲明一下引入我們自己編寫的配置單.

然后在對應自己項目的Android-Lib-Moduel或App-Module就可以直接這么使用.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile libraries.junit
compile libraries.supportAppCompat
compile libraries.supportRecyclerView
}
這樣就可以相對優(yōu)雅的處理好各種依賴的版本一致性問題.

優(yōu)雅的管理so庫

很多時候第三方sdk都會提供多個版本的so庫.而因為可能我們同時都會使用不同的sdk.然后有一些剛好沒提供上.而我們想要正常使用.理應取所有so庫的交集目錄.

如:

armeabi
sdk1.so
sdk2.so
armeabi-v7a
sdk1.so
這種情況下.我們只能使用armeabi的目錄.而刪除掉 armeabi-v7a.因為如果你剛好apk安裝到了架構是 armeabi-v7a 的手機上.他就會解壓apk中的 armeabi-v7a 目錄到/data/data/xxApp/lib. 而顯然sdk2.so是不存在的.這個時候如果你代碼有使用到sdk2.so的話.必然會出現(xiàn)找不到so庫的問題.從而導致crash.

當然.我們可以直接只刪除到剩下 armeabi文件夾.但是這種方式就有點麻煩.因為如果剛好sdk2.so我們發(fā)現(xiàn)業(yè)務不需要了.可以刪了.而sdk1.so我們是有多個平臺編譯的so庫了.為了更加好的效果.我也不在于apk大一點.這種情況下.又要把 armeabi-v7a 的東西copy回來.這樣也太麻煩了.所以.我們通過gradle來實現(xiàn).

首先.編輯項目根目錄下的 gradle.properties文件.
添加一行

...

android.useDeprecatedNdk=true
然后.在app-module的 build.gradle 中

android {
//...
defaultConfig {
//xx
ndk {
//設置支持的SO庫架構
abiFilters 'armeabi'//, 'armeabi-v7a', 'arm64-v8a'//, 'x86', 'x86_64'
}
}
}
直接隨便根據(jù)自己需求來配置需要打包到apk的so庫類型.

自定義生成的apk名稱

as中默認只是生成app-debug.apk.這樣看起來太單調了.看起來一點都不nice.所以我們都喜歡自定義打包生成的apk的名稱能夠自定義.很簡單.只需要在app-module的build.gradle中配置

android {
//...
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent + "/${variant.buildType.name}",
"dreamliner-rvhelperSample-${variant.buildType.name}-V${variant.versionName}.apk".toLowerCase())
}
}
}
效果如下:

配置正式簽名

很多時候我們接入微信/高德地圖.都需要進行正式簽名才可以正常校驗成功和使用.as本身也提供了配置簽名的可視化操作.
如圖:

當然.我們更喜歡的是自己寫配置清單.
首先在app-module下創(chuàng)建自己的簽名和對應的密碼.別名.別名密碼等配置.

jks的創(chuàng)建就不詳細描述了.自行google.主要講的是配置 private.properties文件.
補充相關內容:

RELEASE_STORE_FILE=sample.jks //簽名的名稱
RELEASE_STORE_PASSWORD=123456 //簽名的密碼
RELEASE_KEY_ALIAS=sample //別名名稱
RELEASE_KEY_PASSWORD=123456 //別名的密碼
然后在使用的app-module的build.gradle下再進行配置.

android{
//...
signingConfigs {
release {
def filePrivateProperties = file("private.properties")
if (filePrivateProperties.exists()) {
Properties propsPrivate = new Properties()
propsPrivate.load(new FileInputStream(filePrivateProperties))
storeFile file(propsPrivate['RELEASE_STORE_FILE'])
storePassword propsPrivate['RELEASE_STORE_PASSWORD']
keyAlias propsPrivate['RELEASE_KEY_ALIAS']
keyPassword propsPrivate['RELEASE_KEY_PASSWORD']
}
}
}
}
然后直接在buildType中指定一下使用什么簽名即可.

android{
buildTypes {
debug {
minifyEnabled false
signingConfig signingConfigs.release //指定使用上面配置好的簽名內容
}

    release {
        minifyEnabled true
        shrinkResources true
        signingConfig signingConfigs.release
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

    preview {
        debuggable true // save debug mes
        minifyEnabled true
        shrinkResources true
        signingConfig signingConfigs.release
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

}
常用的差異化構建

比如我現(xiàn)在喜歡在debug的時候.我的app_name是rvHelper-debug.而到正式的時候就用rvHelper.這樣自己使用的時候也能一眼就看出來在使用的是測試/正式的包.

android{
buildTypes {
debug {
resValue 'string', 'APP_NAME', 'rvHelper-debug'
resValue 'string', 'isDebug', 'true'
}

    release {
        resValue 'string', 'APP_NAME', 'rvHelper'
        resValue 'string', 'isDebug', 'false'
    }

    preview {
        resValue 'string', 'APP_NAME', 'rvHelper-preview'
        resValue 'string', 'isDebug', 'true'
    }
}

}
然后直接在 string.xml 中進行配置

<string name="app_name">@string/APP_NAME</string>
而在清單文件上面當然使用 @string/app_name.這樣一配置下來.就可以實現(xiàn)你想要的差異構建的效果.
同理.我想根據(jù)debug/release來初始化的時候做不同的邏輯.比如在Application初始化的時候.

public class AppContext extends Application {

private static AppContext mInstance;

private boolean isDebug;

public static AppContext getInstance() {
    return mInstance;
}

@Override
public void onCreate() {
    super.onCreate();
    mInstance = this;
    initDebug();
    initNet();
    //如初始化net一樣.把相關的圖片加載框架/Log/其他有debug開關的一些依賴.都可以進行差異化構建
}

public boolean isDebug() {
    return isDebug;
}

private void initDebug() {
    isDebug = Boolean.parseBoolean(getString(R.string.isDebug));
}

private void initNet() {
    if (isDebug()) {
        //使用本地服務器/測試服務器的地址
    } else {
        //使用生成服的服務器地址
    }
}

}
這樣就可以很好的進行差異化構建[和多渠道打包同一個概念]

FAQ

開啟multidex的常見錯誤

在我之前的博客中有簡單介紹過如何配置multidex.但是很多時候編譯的時候就會因為javaMaxHeapSize不足導致無法編譯成功.這個時候只需要加入一下配置即可.

android {
//...
dexOptions {
preDexLibraries = false
javaMaxHeapSize "4g"
}

}
exclude重復的jar版本等信息

很多時候我們用不同的jar包.里面都會有版本信息/日志等等文件會一齊進行打包.如果剛好同名.就會導致打包的時候出錯.這個時候只需要根據(jù)報錯提供的名稱來進行exclude即可.如下:

android {
//...
packagingOptions {
exclude 'META-INF/notice.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/services/javax.annotation.processing.Processor'
}

}
依賴aar

首先copy *.aar文件到對應的module的libs目錄.然后在對應的module的build.gradle文件中進行配置.

allprojects {
repositories {
jcenter()
flatDir {
dirs 'libs'
}
}
}

dependencies {
compile(name: 'sampleAar', ext: 'aar')
}
總結

暫時把我平時使用的配置風格都大概過了一下.雖然都只是簡單的介紹.但是基本都還算是完整.能夠滿足項目需求.如果有其他的疑問.歡迎留言.大家進行溝通交流.同時如果我上文中提及到的點有所疏漏.還有各位兄弟們提點一二.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末账月,一起剝皮案震驚了整個濱河市套蒂,隨后出現(xiàn)的幾起案子庸汗,更是在濱河造成了極大的恐慌韵洋,老刑警劉巖摹菠,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異固蛾,居然都是意外死亡结执,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門艾凯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昌犹,“玉大人,你說我怎么就攤上這事览芳。” “怎么了鸿竖?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵沧竟,是天一觀的道長铸敏。 經常有香客問我,道長悟泵,這世上最難降的妖魔是什么杈笔? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮糕非,結果婚禮上蒙具,老公的妹妹穿的比我還像新娘。我一直安慰自己朽肥,他們只是感情好禁筏,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著衡招,像睡著了一般篱昔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上始腾,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天州刽,我揣著相機與錄音,去河邊找鬼浪箭。 笑死穗椅,一個胖子當著我的面吹牛,可吹牛的內容都是我干的奶栖。 我是一名探鬼主播匹表,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驼抹!你這毒婦竟也來了桑孩?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤框冀,失蹤者是張志新(化名)和其女友劉穎流椒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體明也,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡宣虾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了温数。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绣硝。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撑刺,靈堂內的尸體忽然破棺而出鹉胖,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布甫菠,位于F島的核電站挠铲,受9級特大地震影響,放射性物質發(fā)生泄漏寂诱。R本人自食惡果不足惜拂苹,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痰洒。 院中可真熱鬧瓢棒,春花似錦、人聲如沸丘喻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仓犬。三九已至嗅绰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搀继,已是汗流浹背窘面。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叽躯,地道東北人财边。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像点骑,于是被迫代替她去往敵國和親酣难。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容