Android Studio Gradle進階配置

設置 Java 版本

在根目錄下的build.gradle文件下添加 ext{ .... } 中的內容:

ext{
kotlin_version = '1.1.51'
rxandroid = '2.0.1'
anko_version = '0.8.2'
support_version = '26.1.0'
target_sdk_version = 26
compile_sdk_version = 26
min_sdk_version = 15
}

使用規則,字符串需使用“$rootProject.”,整形直接用rootProject.。ext可加可不加

android {
compileSdkVersion rootProject.compile_sdk_version
defaultConfig {
applicationId "com.xxx.xxxx"
minSdkVersion rootProject.ext.min_sdk_version
targetSdkVersion rootProject.ext.target_sdk_version
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.ext.kotlin_version"
implementation "com.android.support:appcompat-v7:$rootProject.support_version"
implementation "io.reactivex.rxjava2:rxandroid:$rootProject.rxandroid"
compile "org.jetbrains.anko:anko-common:$rootProject.anko_version"
compile "com.android.support:recyclerview-v7:$rootProject.support_version"
}

參考:http://www.lxweimin.com/p/abb5bbb99142

全局設定編碼

allprojects {
repositories {
jcenter()
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
}

定義全局變量

先在 project 根目錄下的 build.gradle 定義全局變量:

ext {
minSdkVersion = 16
targetSdkVersion = 24
}

然后在各 module 的 build.gradle 中可以通過rootProject.ext來引用:

android {
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}

定義局部變量

有時候一個庫會被引用多次,或者一個庫有多個依賴,但這些依賴的版本都是統一的。我們通過ext來定義一些變量,這樣在用到的時候就可以統一使用了。

ext {
leakcanaryVersion = '1.3.1'
scalpelVersion = "1.1.2" // other param
}

debugCompile "com.squareup.leakcanary:leakcanary-android:$leakcanaryVersion"
releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:$leakcanaryVersion"

exlude關鍵字

我們經常會遇到庫沖突的問題,這個在多個部門協作的大公司會更常見到。將沖突的庫通過exclude來做剔除是一個好方法。
1.剔除整個組織的庫

compile ('com.facebook.fresco:animated-webp:0.13.0') {
exclude group: 'com.android.support' // 僅僅寫組織名稱
}

2.剔除某個庫

compile('com.android.support:appcompat-v7:23.2.0') {
exclude group: 'com.android.support', module: 'support-annotations' // 寫全稱
exclude group: 'com.android.support', module: 'support-compat'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'support-vector-drawable'
}

引用本地aar

1.把aar文件放在某目錄內,比如就放在某個 module 的 libs 目錄內
2.在這個 module 的 build.gradle 文件中添加:

repositories {
flatDir {
dirs 'libs' //this way we can find the .aar file in libs folder
}
}

3.之后在其他項目中添加下面的代碼后就引用了該 aar

dependencies {
compile(name:'aar的名字(不用加后綴)', ext:'aar')
}

如果你希望把 aar 放在項目的根目錄中,也可以參考上面的配置方案。在根目錄的build.gradle中寫上:

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

依賴項目中的 module 和 jar

依賴項目中的 module 和 jar

dependencies {
compile project(':mylibraryModule')
compile files('libs/sdk-1.1.jar')
}

配置獨立的簽名信息

通常我們可以直接把簽名的明文信息寫在 gradle 配置文件中,但是在開源代碼的時候不是很方便,前者可能存放簽名文件的位置需要修改,后者則希望隱藏簽名信息,在看不少開源項目的時候,發現很多是這樣做的 signingConfigs 位置, android 的下一級

signingConfigs {
release_key{
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}

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

在對應位置引用常量,在 properties 中再進行具體賦值,這樣不會直接暴露簽名信息,也方便配置
在 gradle.properties 中

RELEASE_KEY_PASSWORD=xxxx
RELEASE_KEY_ALIAS=xxx
RELEASE_STORE_PASSWORD=xxx
RELEASE_STORE_FILE=../.keystore/xxx.jks

多渠道打包

在 product flavor 下定義不同類型, 把 AndroiManifest 中的 channel 替換
ductFlavors 位置: android 的下一級

android {
productFlavors {
fir {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "fir"]
}
GooglePlay {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "GooglePlay"]
}
Umeng {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Umeng"]
}
}
}

替換 AndroiManifest 中的字段

<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}"/>

減少編譯錯誤和忽略 lint 檢查

packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/notice.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/dependencies.txt'
exclude 'META-INF/LGPL2.1'
}
lintOptions {
abortOnError false
}

生成自定義 App 名稱,在Android標簽添加如下代碼

applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
// 輸出apk名稱為ForWatch_v1.1(2)2016-09-28_15-54-35.apk
def version = "v${versionName}-${versionCode}"
def endIndex = outputFile.name.indexOf('.apk')
def apkName = outputFile.name.substring(0, endIndex);
def fileName = "${apkName}
${version}${buildTime()}${revision()}.apk"
//output.outputFile = new File(outputFile.parent, fileName)
outputFileName = fileName
}
}
}

自定義apk的生成目錄(含有自定義app名稱的代碼)

android {
……//省略部分代碼
applicationVariants.all {
//判斷是release還是debug版本
def buildType = it.buildType.name
def fileName
//下面的channel是獲取渠道號,你獲取渠道號不一定會和我的代碼一樣,因為有可能你的渠道名稱的規則和我的不一樣,我的規則是${渠道名}-${applicationId},所以我是這樣取的。
def channel = it.productFlavors[0].name.split("-")[0]
//獲取當前時間的"YYYY-MM-dd"格式。
def createTime = new Date().format("YYYY-MM-dd", TimeZone.getTimeZone("GMT+08:00"))
//只對Release包起作用,如果不是Release包則不變更輸出路徑,否則可能導致AS無法自動安裝debug包。
if (buildType == "release") {
it.getPackageApplication().outputDirectory = new File(project.rootDir.absolutePath + "/apks/${it.productFlavors[0].applicationId}/${createTime}")
}
it.outputs.each {
//只對Release包起作用,如果不是Release包則不變更名稱。
if (buildType == "release") {
//我此處的命名規則是:渠道名項目名版本名創建時間構建類型.apk
fileName = "${channel}_項目名稱v${defaultConfig.versionName}${createTime}-${buildType}.apk"
//將名字打印出來,以便及時查看是否滿意。
println "文件名:-----------------${fileName}"
//重新對apk命名。(適用于Gradle4.0以下版本)
//it.outputFile = new File(it.outputFile.parent, fileName)
//重新對apk命名。(適用于Gradle4.0(含)以上版本)如果你Gradle版本是4.0以下版本則將上面的一行代碼放開并注釋下面的這一行。
it.outputFileName = fileName
}
}
}
……//省略部分代碼
}

參考:https://blog.csdn.net/kelin410/article/details/75500821

指定資源目錄

自定義 java 代碼和 res 資源的目錄,更加靈活

android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
if (!IS_USE_DATABINDING) { // 如果用了databinding
jniLibs.srcDirs = ['libs']
res.srcDirs = ['res', 'res-vm'] // 多加了databinding的資源目錄
} else {
res.srcDirs = ['res']
}
}
test {
java.srcDirs = ['test']
}
androidTest {
java.srcDirs = ['androidTest']
}
}
}

在 BuildConfig.class 中增加靜態變量

有時候我們想根據不同的版本,設置相同變量不同的值,最常見的使用場景就是 Log 工具類,通過設置 isDubug 不同值,只有 debug 版本的 app 會產生 log 日志,設置過程如下:

buildTypes {
release {
buildConfigField("boolean", "isDebug", "false") // 定義 isdubug 的值
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug{
buildConfigField("boolean", "isDebug", "true")
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

在 sync 后BuildConfig中就有你定義的這個變量(isDebug)。

public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.hiwhitley.himei";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
// Fields from build type: debug
public static final boolean isDebug = true;
}

如果有帶引號的 string,要記得轉義:

buildConfigField "String", "URL_ENDPOINT", ""http://your.development.endpoint.com/""

參考:

Gradle配置最佳實踐
Android Studio 中 gradle 的一些玩法
Gradle 語法

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • Gradle配置最佳實踐 本文會不定期更新,推薦watch下項目。如果喜歡請star,如果覺得有紕漏請提交issu...
    Solang閱讀 1,651評論 0 4
  • 說明 本文主要介紹和Gradle關系密切、相對不容易理解的配置,偏重概念介紹。部分內容是Android特有的(例如...
    jzj1993閱讀 15,694評論 1 62
  • 參考 中文官網構建指南:https://developer.android.google.cn/studio/bu...
    FinalSky閱讀 5,403評論 0 16
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,765評論 25 708
  • 最近中毒太深,每天一拿手機就刷頭條,不是看新聞八卦,而是看各種小戶型裝修,幾近瘋狂。 控制不住腦袋里...
    滟昕閱讀 345評論 4 3