參考
https://developer.android.com/studio/build
http://google.github.io/android-gradle-dsl/current/index.html
https://developer.android.com/reference/tools/gradle-api/classes
說明
學習gradle最煩人的就是api不知道去哪查詢,想要實現某個打包功能只能去網上copy人家的,
gradle官方的文檔還好,但Android gradle plugin的官方文檔卻更新不及時,原來的文檔一直是3.4的,
現在竟然完全刪除了,真tm狗東西,現在只有api了,想要深入只能通過complieOnly導入gradle依賴,下邊有說明。
android gradle plugin版本查詢
https://developer.android.com/studio/releases/gradle-plugin
gradle plugin和gradle版本對應
| Plugin version |
Required Gradle version |
| 1.0.0 - 1.1.3 |
2.2.1 - 2.3 |
| 1.2.0 - 1.3.1 |
2.2.1 - 2.9 |
| 1.5.0 |
2.2.1 - 2.13 |
| 2.0.0 - 2.1.2 |
2.10 - 2.13 |
| 2.1.3 - 2.2.3 |
2.14.1+ |
| 2.3.0+ |
3.3+ |
| 3.0.0+ |
4.1+ |
| 3.1.0+ |
4.4+ |
| 3.2.0 - 3.2.1 |
4.6+ |
| 3.3.0 - 3.3.3 |
4.10.1+ |
| 3.4.0 - 3.4.3 |
5.1.1+ |
| 3.5.0 - 3.5.4 |
5.4.1+ |
| 3.6.0 - 3.6.4 |
5.6.4+ |
| 4.0.0+ |
6.1.1+ |
| 4.1.0+ |
6.5+ |
Extension types
Listed below are the Gradle extension types used by respective plugins:
| Type |
Description |
| The android extension for application plugins. |
|
| The android extension for com.android.library projects. |
|
| android extension for com.android.test projects. |
|
| The android extension for com.android.feature projects. |
Configuration blocks
下邊列出了在android{}的closure中可訪問的配置
| Block |
Description |
| Specifies options for the Android Asset Packaging Tool (AAPT). |
|
| Specifies options for the Android Debug Bridge (ADB), such as APK installation options. |
|
| Encapsulates all build type configurations for this project. |
|
| Specifies Java compiler options, such as the language level of the Java source code and generated bytecode. |
|
| Specifies options for the Data Binding Library. |
|
| Specifies defaults for variant properties that the Android plugin applies to all build variants. |
|
| Specifies options for the DEX tool, such as enabling library pre-dexing. |
|
| Configure JaCoCo version that is used for offline instrumentation and coverage report. |
|
| Specifies options for the lint tool. |
|
| Specifies options and rules that determine which files the Android plugin packages into your APK. |
|
| Encapsulates all product flavors configurations for this project. |
|
| Encapsulates signing configurations that you can apply to BuildType and ProductFlavor configurations. |
|
| Encapsulates source set configurations for all variants. |
|
| Specifies configurations for building multiple APKs or APK splits. |
|
| Specifies options for how the Android plugin should run local and instrumented tests. |
AppExtension
其實對應的就是app中的build.gradle中的android,它對應的類型是BaseAppModuleExtension,繼承關系如下:
- BaseAppModuleExtension實現了AppExtension,ApplicationExtension,
- ApplicationExtension實現了 CommonExtension,ApkExtension,TestedExtension
BaseAppModuleExtension是內部的api,在api文檔中被隱藏了,其實大部分的屬性方法都是在CommonExtension中定義的。
variantFilter
https://developer.android.com/studio/build/build-variants.html#filter-variants
variantFilter(Action<VariantFilter> filter)
在這里你可以對variant進行過濾,通過調用VariantFilter.setIgnore(true)。
android { ... variantFilter { variant -> def buildTypeName = variant.buildType*.name def flavorName = variant.flavors*.name if (flavorName.contains("dev") && buildTypeName.contains("release")) { // Tells Gradle to ignore each variant that satisfies the conditions above. setIgnore(true) } } }
applicationVariants
DomainObjectSet<ApplicationVariant> applicationVariants
ApplicationVariant在com.android.build.gradle.api.ApplicationVariant
你可以在這里獲取到最終的可構建的variant,你可以在此處對各variant進行屬性修改。
另外由於此集合時DomainObjectSet,所以應該使用.all來遍歷,而不是each,原因是插件只在project is evaluated之后才填充此集合。
android.applicationVariants.all { variant ->
StringBuilder sb = new StringBuilder()
for (def productFlavor : variant.productFlavors) {
sb.append(productFlavor.name)
}
println "productFlavor:$sb, buildType:$variant.buildType.name, applicationId:$variant.applicationId"
def mergedFlavor = variant.getMergedFlavor()
if ("debug".equalsIgnoreCase(variant.buildType.name)) {
mergedFlavor.applicationId = "com.fuck.you"
mergedFlavor.manifestPlaceholders = [hostName:"www.example.com/${variant.versionName}"]
}
}
通過variant.getMergedFlavor()獲取最后組合的flavor,通過這個productFlavor可以修改最后的包名、placeholder等等屬性。
自定義打包后要輸出的目錄
def releaseTime() { return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) } android{ applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { File outputDirectory = new File(outputFile.parent); def fileName if (variant.buildType.name == "release") { fileName = "app_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk" } else { fileName = "app_v${defaultConfig.versionName}_${packageTime()}_debug.apk" } output.outputFile = new File(outputDirectory, fileName) } } } }
在Android Gradle Plugin 4.x中Variant新的配置方式
https://medium.com/androiddevelopers/new-apis-in-the-android-gradle-plugin-f5325742e614
以下是Android項目構建所經歷的階段的概述:
1. 運行Build scripts,允許構建和插件配置Android Gradle Plugin DSL對象以及注冊variant 回調。
2. Android Gradle Plugin 結合了build types和product flavors來創建variants 和test components。
3. 將為每個variant調用onVariants,從而允許自定義variant設置,並為每個測試組件均調用onTestComponent。
4. 將為每個啟用的variant調用onVariantProperties,並為每個啟用的測試組件調用onTestComponentProperties,從而允許注冊使用或修改構建中間件的任務。
5. 在調用onVariants和onVariantProperties回調后,Android Gradle Plugin 插件會為variant注冊task。
6. 使用已注冊task,為每個variant調用先前的variant API。
7. Gradle計算task graph,構建即可開始執行。
import com.android.build.api.variant.impl.ApplicationVariantPropertiesImpl import com.android.build.api.variant.impl.ApplicationVariantImpl import com.android.build.gradle.internal.dsl.BaseAppModuleExtension apply plugin: 'com.android.application' android { BaseAppModuleExtension appModuleExtension -> onVariants { ApplicationVariantImpl applicationVariant -> StringBuilder sb = new StringBuilder() sb.append("name:" + applicationVariant.name + ", ") sb.append("flavorName:" + applicationVariant.flavorName + ", ") sb.append("productFlavors:" + applicationVariant.productFlavors + ", ") sb.append("buildType:" + applicationVariant.buildType + ", ") println sb } onVariantProperties { ApplicationVariantPropertiesImpl applicationVariantProperties -> StringBuilder sb = new StringBuilder() sb.append("productFlavor:$applicationVariantProperties.name, ") sb.append("buildType:$applicationVariantProperties.buildType, ") sb.append("applicationId:" + applicationVariantProperties.applicationId.get() + ", ") println sb // API 'MergedFlavor.getApplicationId()' is obsolete and has been replaced with 'VariantProperties.getApplicationId()'. // It will be removed in version 5.0 of the Android Gradle plugin. if ("debug".equalsIgnoreCase(applicationVariantProperties.buildType)) { applicationVariantProperties.applicationId.set(mlwDebugApplicationId) } //修改打包的名字 applicationVariantProperties.outputs.each { output -> def date = new Date().format('yyyy_MMdd_HHmm') def file = output.outputFileName.get() def fileName = file.replace(".apk", "_" + android.defaultConfig.versionName + "_" + date + ".apk").replaceFirst("app", "rent_customer").replace("-", "_") output.outputFileName.set(fileName) // println "output.outputFileName:" + output.outputFileName } } }
上邊的導入的api需要添加依賴才不會變紅
compileOnly group: 'com.android.tools.build', name: 'gradle', version: '4.1.0'
在 Android Gradle Plugin 5.0中R.xxx不再是final
https://sites.google.com/a/android.com/tools/tips/non-constant-fields
Resource IDs will be non-final in Android Gradle Plugin version 5.0, avoid using them in switch case statements
一般我們會在onClick中使用switch(id)來檢索對應操作,
public void onClick(View v) { switch (v.getId()) { case R.id.iv_close: { dismiss(); break; } case R.id.bt_share: { if (onClickListener != null) { onClickListener.onClick(v); } dismiss(); break; } } }
但在Android Gradle Plugin version 5.0中,資源id都不是final了,而switch在編譯器就把R.id.xx的值寫入到class中,不是final就意味着可能發生改變,那么在運行時的時候可能就找不到對應的case了,
解決方法就是:
把switch換成if else,在as中選中switch關鍵字,然后鍵盤輸入show context action的快捷鍵(我的是alt+enter),就會彈出快捷轉換操作。

