Android之Gradle多Module常见配置修改和优化

1.Gradle生命周期?

参考:Android之Gradle构建生命周期_Tiger的专栏-CSDN博客

2.Gradle应用场景有哪些?

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。 面向Java应用为主。当前其支持的语言C++、Java、Groovy、Kotlin、Scala和Swift,计划未来将支持更多的语言。

3.Project下常见执行gradle下的Tasks?

gradle会给我们插入许多适用于Android的gradle task,我们点击IDE,右边的Gradle图标查看;

Android之Gradle多Module常见配置修改和优化_第1张图片

 双击tasks任务查看gradle已经支持的任务:

Android之Gradle多Module常见配置修改和优化_第2张图片

以下提供了这些官方gradle task的介绍

Android tasks
-------------
androidDependencies - 显示项目的Android依赖项。
signingReport - 显示每个渠道包的签名信息。
sourceSets - 打印出此项目中定义的所有资源。

Build tasks (打包时用的比较多)
-----------
assemble - 打包所有应用程序和依赖的所有渠道包。
assembleAndroidTest - 打包所有测试类型的应用程序。
assembleDebug - 打包所有Debug版本
assembleRelease - 打包所有Release版本
build - 打包所有,包括测试项内容
buildDependents - 打包并测试该项目以及它的所有的依赖项。
buildNeeded - 同上。
clean - 删除构建目录
cleanBuildCache - 删除构建的缓存目录。
mockableAndroidJar - 创建一个适合单元测试的android.jar版本。

Help tasks
----------
buildEnvironment - 显示在项目':app'中声明的所有buildscript依赖项。
components - 显示项目':app' components的组件。 
dependencies - 显示项目':app'中声明的所有依赖项。
dependencyInsight - 显示对项目':app'中特定依赖项的观察。
dependentComponents - 显示项目':app'中组件的相关组件。
help - 显示帮助消息。
model - 显示项目':app'的配置模型。
projects - 显示项目':app'的子项目。
properties - 显示项目':app'的配置项。
tasks - 显示项目':app'所有可运行的task。

Install tasks
-------------
installDebug -  安装Debug版本。
installDebugAndroidTest - 为Debug版本安装android(在设备上)测试。
uninstallAll - 卸载所有应用程序。
uninstallDebug - 卸载Debug版本。
uninstallDebugAndroidTest - 卸载Debug版本的android(在设备上)测试。
uninstallRelease - 卸载发布版本。

Verification tasks (校验项)
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
lintVitalRelease - Runs lint on just the fatal issues in the release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

当然,task的数量会根据你所依赖的库增加,如果要使用某个task,可以先运行一下help下的task进行查看。

4.多模块Gradle常见配置有哪些?

4.1根目录下全局build.gradle配置FloatWindowL/build.gradle

  • buildscript{}闭包里是gradle脚本执行所需依赖,分别是对应的maven库和插件;
  • allprojects{}闭包里是项目本身需要的依赖,比如项目所需要的maven库;
  • task clean(type: Delete){}是运行gradle clean时,执行此处定义的task任务,该任务继承自Delete,删除根目录中的build目录;其中buildscript包含repositories闭包和dependencies闭包;

全局build.gradle配置分为三部分:

buildscript{}闭包

buildscript {  //gradle脚本执行所需依赖,分别是对应的maven库和插件;
    repositories {  //配置远程仓库      
        maven {     //公司内部maven库   
            url "http://localhost:8080/plugin"
            credentials {
                username = "xxx"
                password = "xxxxxx"
            }
        }
        maven {  //华为Maven库
            url 'https://developer.huawei.com/repo'
        }
        maven{   //阿里云maven库
                url 'http://maven.aliyun.com/nexus/content/groups/public/'
        }
    }
    dependencies {   //依赖插件
        //Android Plugin for Gradle
        classpath 'com.android.tools.build:gradle:3.2.1' //gradle plugin 
        //神策gradle依赖
        classpath 'com.sensorsdata.analytics.android:android-gradle-plugin2:3.2.9'
        classpath '自定义插件...'
    }
}

allprojects{}闭包

allprojects { //项目本身需要的依赖,比如项目所需要的maven库
    repositories {  //配置远程仓库       
        maven {     
                //公司内部maven库    
                url "http://localhost:8080/plugin" 
                        credentials { 
                                username = "xxx" password = "xxxxxx" 
                        } 
        } 
        maven {    //华为Maven库 
                url 'https://developer.huawei.com/repo' 
        } 
        maven{   //阿里云maven库
                url 'http://maven.aliyun.com/nexus/content/groups/public/'
        } 
    }
    ext { //自定义扩展属性
        compileSdkVersion = getProperty("COMPILE_SDK_VERSION") as Integer
        buildToolsVersion = getProperty("BUILD_TOOLS_VERSION")
        targetSdkVersion = getProperty("TARGET_SDK_VERSION") as Integer
        minSdkVersion = getProperty("MIN_SDK_VERSION") as Integer
    }
}

task clean(type: Delete){}闭包

task clean(type: Delete) { //该任务继承自Delete,删除根目录中的build目录
    delete rootProject.buildDir
}

自定义第三方库和自定义的声明,其他Module统一引用,有效降低个Module使用库不一致问题

ext.deps = [
SOkHttp : 'com.squareup.okhttp3:okhttp:'+getProperty('OKHTTP_VERSION'),
SOkHttpLog : 'com.squareup.okhttp3:logging-interceptor:'+getProperty('OKHTTPLOG_VERSION'),
GCrash : 'com.xxx.xxxx:crash:' + getProperty('AAR_MCP_VERSION') + '@aar',
...
]

注意实现:

定义getProperty("OKHTTP_VERSION")属性OKHTTP_VERSION,在FloatWindowL/gradle.propeties里面定义的:

OKHTTP_VERSION=3.12.12
...

定义ext.deps和ext属性如何引用:

rootProject.ext.compileSdkVersion 
rootProject.ext.deps.SOkHttp或者deps.SOkHttp

4.2非主Module下build.gradle配置?

4.2.1定义非主Module引用的通用gradle(module.gradle和maven.gradle)

Android之Gradle多Module常见配置修改和优化_第3张图片

  • module.gradle定义通用的属性;
  • maven.gradle定义上传到指定maven服务器配置;

module.gradle定义通用的属性定义如下:


def version_code = 116
apply plugin: 'com.android.library'
android {
    //使用跟build.gradle定义的
    //compileSdkVersion = getProperty("COMPILE_SDK_VERSION") as Integer
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    //Android 6.0不再支持 Apache HTTP client, 建议使用 HttpURLConnection 代替。
    //如果还想要继续使用 Apache HTTP client 的,请在build.gradle中添加下面的代码
    useLibrary 'org.apache.http.legacy'
    //默认配置
    defaultConfig {
        if(project.ext.has("versionCode")){
            versionCode project.ext.getProperty("versionCode") as Integer
        }else {
            versionCode version_code
        }
        versionName project.ext.getProperty("version") as String

        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        //----DefaultExtraPropertiesExtension----
        if(project.ext.has("moduleName")){
            ndk{
                moduleName project.ext.getProperty("moduleName")
                //abiFilters "armeabi", "armeabi-v7a", "x86"
                setAbiFilters project.ext.has("abiFilters") ? project.ext.getProperty("abiFilters") : ["armeabi-v7a"]
            }
        }
    }

    // 生产/测试环境配置
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    //程序在编译的时候会检查lint,有任何错误提示会停止build,我们可以关闭这个开关
    lintOptions {
        abortOnError false //即使报错也不会停止打包
    }

}

//modify by Seven ; fix Gradle Upgrade
android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath=true

maven.gradle定义上传到指定maven服务器配置如下:

apply plugin: 'maven'

def getValueByKey(String key) {
    String value = System.getenv()[key]
    if (value != null && value != "") {
        return value
    } else {
        return hasProperty(key) ? getProperty(key) : ""
    }
}

uploadArchives {
    //配置插件要发布的Maven地址
    repositories.mavenDeployer {
        name = 'AARDeployer'
        repository(url: getValueByKey('MAVEN_URL')) {
            authentication(userName: getValueByKey('MAVEN_USER'), password: getValueByKey('MAVEN_PASS'))
        }
        pom.version = project.ext.version
        pom.artifactId = project.ext.artifactId
        pom.groupId = project.ext.groupId
        pom.name = project.ext.artifactId
        pom.packaging = project.ext.packaging
    }
}

4.2.2定义非主Module下build.gradle引用module.gradle和maven.gradle

ext {
    version = getProperty("AAR_GMALL_PAGE_VERSION")
    artifactId = "yifanpage"
    groupId = "com.yifan.ecmall"
    packaging = "aar"
    resourcesPrefix="yifan_"
}
//应用非app_module通用模块gradle配置
apply from: project.rootProject.uri('module.gradle')

android {

    dataBinding {
        enabled = true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //引入其他库
    implementation (deps.SOkHttp)
    //在后面加上@aar,意指你只是下载该aar包,而并不下载该aar包所依赖的其他库,
    // 那如果想在使用@aar的前提下还能下载其依赖库,则需要添加transitive=true的条件
    implementation('xxxx:xxx:100.100.1@aar'){
        //transitive用于自动处理子依赖项。默认为true,gradle自动添加子依赖项,
        //形成一个多层树形结构;设置为false,则需要手动添加每个依赖项。
        transitive = true
    }
}
//应用maven上传插件配置
apply from: project.rootProject.uri('maven.gradle')

4.3主Module下build.gradle配置?

4.3.1主Module下build.gradle配置

//扩展字段
ext {
    //版本号
    g_versionCode = 1
    //版本名
    g_versionName = '1.0.1'
    //升级版本号
    g_updateCode = '"1.0.1"'
}
//可以做为独立APP
apply plugin: 'com.android.application'
//应用华为推送插件
apply plugin: 'com.huawei.agconnect'

apply from: project.uri('deps/yifandeps.gradle')


android {
    //设置项目编译时用的Android版本
    compileSdkVersion rootProject.ext.compileSdkVersion as Integer
    //设置编译时使用的构建工具版本,Android Studio3.0后去除此项配置;
    buildToolsVersion rootProject.ext.buildToolsVersion
    //Android 6.0不再支持 Apache HTTP client, 建议使用 HttpURLConnection 代替。
    //如果还想要继续使用 Apache HTTP client 的,请在build.gradle中添加下面的代码
    useLibrary 'org.apache.http.legacy'

    //程序在编译的时候会检查lint,有任何错误提示会停止build,我们可以关闭这个开关
    lintOptions {
        abortOnError false //即使报错也不会停止打包
        checkReleaseBuilds false  //打包release版本的时候进行检测
    }

    defaultConfig {
        applicationId "com.yifan.eshopnew"
        versionCode g_versionCode as Integer
        versionName g_versionName as String

        minSdkVersion rootProject.ext.minSdkVersion as Integer
        targetSdkVersion rootProject.ext.targetSdkVersion as Integer
        multiDexEnabled true    //添加多 dex分包支持
        //resourcePrefix "yifan_plus_" //资源前缀,模块下相关string,drawable等资源前缀
        manifestPlaceholders = [PACKAGE_NAME: "com.yifan.eshopnew", AMAP_API_KEY: "xxxxxxxx"] //manifestPlaceholders 可以替换androidmanifest文件中的标签,可作为快速渠道打包替换渠道名的一种方式,也可以自定义标签用来替换需要的文本,多作为不同环境不同key的修改;
        //fix:All flavors must now belong to a named flavor dimension by Seven
        //版本名后面添加一句话,意思就是flavor dimension 它的维度就是该版本号,这样维度就是都是统一的了
        flavorDimensions "default"
    }

    dataBinding {//支持数据绑定
        enabled = true
    }
    
    //dexOptions 会映射为 com.android.build.gradle.internal.dsl.DexOptions 类
    dexOptions {
        javaMaxHeapSize "4g" //设置运行 dx 的最大内存
        preDexLibraries false //预编译 dex 库;在我们build的时候会快些,但clean时便会慢,默认开启
        additionalParameters = ["--set-max-idx-number=62000"] //用于添加 dex 的命令。可以通过 dx --help 查看支持的命令和描述。
        jumboMode true //每个 dex 的字符串索引也有限制,正常情况下为 2^16 个。但开启jumboMode 模式,可以支持到 2^32。但是值得注意的是,这个并不是 64K方法数量限制问题的一种方案。
    }

    signingConfigs { // 自动化打包配置
        if (!rootProject.ext.mcpPkg) {
//            release {
//                storeFile file(getKeyStore())      //签名文件
//                storePassword getKeyStorePassword()
//                keyAlias getAlias()
//                keyPassword getKeyAliasPassword()  //签名密码
//            }
        }
    }

    buildTypes { // 生产/测试环境配置
        release {
            if (!rootProject.ext.mcpPkg) {
//                signingConfig signingConfigs.release
            }
            //编译时可以使用buildConfigField向BuildConfig类中写入常量
            //public final class BuildConfig {
            //public static final String GDEBUG = false
            //}

            buildConfigField 'boolean', 'GDEBUG', g_debug
            buildConfigField 'String', 'GUPDATECODE', g_updateCode
            buildConfigField 'boolean', 'APPMEASURE', g_appmeasure
            minifyEnabled true //是否对代码进行混淆
            proguardFiles 'proguard-rules.pro' //指定混淆的规则文件
        }
        debug {
            if (!rootProject.ext.mcpPkg) {
//                signingConfig signingConfigs.release
            }
            buildConfigField 'boolean', 'GDEBUG', g_debug
            buildConfigField 'String', 'GUPDATECODE', g_updateCode
            buildConfigField 'boolean', 'APPMEASURE', g_appmeasure
            minifyEnabled true
            proguardFiles 'proguard-rules.pro'
        }
    }
    
    //当项目中依赖的第三方库越来越多时,有可能会出现两个依赖库中存在同一个(名称)文件。如果这样,Gradle在打包时就会提示错误(警告)。那么就可以根据提示,然后使用以下方法将重复的文件剔除,比较常用的是通过exclude去除重复的文件
    packagingOptions { //打包时的相关配置
        exclude "/libs/*.jar"
    }
    
    //编译使用的java版本
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    //Splits 会映射为 com.android.build.gradle.internal.dsl.Splits 类,没有继承任何类
    splits {
        //Splits 会映射为 com.android.build.gradle.internal.dsl.Splits 类
        //splits 主要是用于打包时的拆包,所以我们需要的是进行apk的打包编译
        abi {
            enable true //对 abi 进行分包处理
            //清除默认架构列表。当我们开启abi 分包时,gradle会帮我们初始化一个架构列表,例如 enable 小节中,我们并没有设置任何架构,而gradle会帮我们分出 “arm64-v8a”、“armeabi-v7a”、“x86”、“x86_64”
            // 重置包含的目录
            reset()
            //设置我们需要的架构。注意的是,我们需要先使用reset方法将默认列表清空,然后再设置。
            include 'armeabi-v7a'
            //是否编译一个包含全部架构的apk
            universalApk false
        }
    }
}

//---公共插件------------------------------------------------------
apply from: project.uri('othertask/commons.gradle')
//---定义属性变量------------------------------------------------------
def getKeyStore() {
    String keyStore = System.getenv()['KEY_STORE']
    if (keyStore != null && keyStore != "") {
        return keyStore
    } else {
        return hasProperty('KEY_STORE') ? KEY_STORE : ""
    }
}

def getAlias() {
    String keyAlias = System.getenv()['KEY_ALIAS']
    if (keyAlias != null && keyAlias != "") {
        return keyAlias
    } else {
        return hasProperty('KEY_ALIAS') ? KEY_ALIAS : ""
    }
}

def getKeyStorePassword() {
    String keyStorePass = System.getenv()['KEY_STORE_PASSWORD']
    if (keyStorePass != null && keyStorePass != "") {
        return keyStorePass
    } else {
        return hasProperty('KEY_STORE_PASSWORD') ? KEY_STORE_PASSWORD : ""
    }
}

def getKeyAliasPassword() {
    String keyAliasPass = System.getenv()['KEY_ALIAS_PASSWORD']
    if (keyAliasPass != null && keyAliasPass != "") {
        return keyAliasPass
    } else {
        return hasProperty('KEY_ALIAS_PASSWORD') ? KEY_ALIAS_PASSWORD : ""
    }
}
//modify by Seven ; fix Gradle Upgrade
android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath=true

4.3.2主Module下build.gradle应用的yifandeps.gradle配置

configurations{
    //去除重复的依赖
    compile.exclude group:'xxxx', module:'xxxx'
}

dependencies {
    implementation deps.GImage
    // 那如果想在使用@aar的前提下还能下载其依赖库,则需要添加transitive=true的条件
    implementation('xxxx:xxx:100.100.1@aar'){
        //transitive用于自动处理子依赖项。默认为true,gradle自动添加子依赖项,
        //形成一个多层树形结构;设置为false,则需要手动添加每个依赖项。
        transitive = true
    }
    implementation deps.Gsuperplayerkit
}

4.3.3主Module下build.gradle应用的commons.gradle配置

// 路由配置
apply plugin: 'com.xxxx.router'

4.4Module如何发布组件?

配置maven插件,参考maven.gradle;

Android之Gradle多Module常见配置修改和优化_第4张图片

 执行uploadArchives的任务上传maven依赖服务器;

以上是我们实际项目主module和非module配置,可以做参考,欢迎补充;

参考:

Android 自带的 gradle task 具体说明_xuehaiwuya1212的博客-CSDN博客

dexOptions——安卓gradle_猛猛的小盆友的博客-CSDN博客_dexoptions

splits——安卓gradle_猛猛的小盆友的博客-CSDN博客_gradle splits

Android必知必会-Android Studio下配置和使用Lambda_他叫自己Mr.张-CSDN博客

​​​​​​Gradle 中 buildConfigField的巧妙应用_死磕到底-CSDN博客

Android Studio3.0 flavorDimensions多维度理解(版本差异化打包)_GSQ_Cat-CSDN博客

手把手教你接入华为分析的Android SDK_jessciasun的博客-CSDN博客

你可能感兴趣的:(Android面试整理2021,Gradle配置,gradle,build,maven)