Android gradle Plugin


參考

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

AppExtension

The android extension for application plugins.

LibraryExtension

The android extension for com.android.library projects.

TestExtension

android extension for com.android.test projects.

FeatureExtension

The android extension for com.android.feature projects.

Configuration blocks

下邊列出了在android{}的closure中可訪問的配置

Block

Description

aaptOptions { }

Specifies options for the Android Asset Packaging Tool (AAPT).

adbOptions { }

Specifies options for the Android Debug Bridge (ADB), such as APK installation options.

buildTypes { }

Encapsulates all build type configurations for this project.

compileOptions { }

Specifies Java compiler options, such as the language level of the Java source code and generated bytecode.

dataBinding { }

Specifies options for the Data Binding Library.

defaultConfig { }

Specifies defaults for variant properties that the Android plugin applies to all build variants.

dexOptions { }

Specifies options for the DEX tool, such as enabling library pre-dexing.

externalNativeBuild { }

Configures external native build using CMake or ndk-build.

jacoco { }

Configure JaCoCo version that is used for offline instrumentation and coverage report.

lintOptions { }

Specifies options for the lint tool.

packagingOptions { }

Specifies options and rules that determine which files the Android plugin packages into your APK.

productFlavors { }

Encapsulates all product flavors configurations for this project.

signingConfigs { }

Encapsulates signing configurations that you can apply to BuildType and ProductFlavor configurations.

sourceSets { }

Encapsulates source set configurations for all variants.

splits { }

Specifies configurations for building multiple APKs or APK splits.

testOptions { }

Specifies options for how the Android plugin should run local and instrumented tests.

AppExtension

其實對應的就是app中的build.gradle中的android,它對應的類型是BaseAppModuleExtension,繼承關系如下:

  • BaseAppModuleExtension實現了AppExtensionApplicationExtension
  • ApplicationExtension實現了 CommonExtensionApkExtensionTestedExtension

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),就會彈出快捷轉換操作。

wps3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM