哪怕不学Gradle,这些开发中的常见操作,你也值得掌握(上)

简介: Gradle 是每个 Android 同学都逃不开的一个话题。

Gradle 是每个 Android 同学都逃不开的一个话题。

你是否看到别人的 Gradle 文件干净又卫生?而自己的又是一团乱麻🏷

不用怕,本篇将结合我的开发日常,将一些常用的操作分享出来,希望可以帮到像我一样不怎么会[玩]Gradle 的同学,相信会对大家有所帮助。

模板代码提取

这是最基础的操作了,对于一个普通 model.gradle ,默认的配置如下:

如果我们每个 model 都这样写,那岂不是很麻烦,那么让我们提取通用代码:

优化步骤

新建一个 gradle 文件,命名为 xxx.gradle ,复制上述 model 里的配置,放到你的项目中,可以自定义修改一些通用内容,在其他model 中依赖即可,如下所示:

这是一个播放器model

// 这就是刚才新建的默认gradle文件,
// 注意:如果你的default.gradle是在项目目录下,请使用../,如果仅在app下,请使用./
apply from: "../default.gradle"
import xxx.*
android {
    // 用于隔离不同model的资源文件
    resourcePrefix "lc_play_"
}
dependencies {
    compileOnly project(path: ':common')
    api xxx
}

上述的 android{} , dependencies{}

其内部的内容都会在 default.gradle 的基础上叠加,对于唯一的键值对,会进行替换。

定义统一的config配置

在项目中,你是如何去写你的版本号等其他默认配置呢?

2345_image_file_copy_6.jpg

对于一个新项目,其默认的配置如下所示,每次新创建 model ,也需要定义其默认参数,如果每次都直接在这里去改动,那么如果版本变化,意味着我们需要修改多次,这并不是我们想看到的效果。

优化步骤

新建 config.gradle ,内容如下:

// 一些配置文件的保存
// 使用git的commit记录当做versionCode
static def gitVersionCode() {
    def cmd = 'git rev-list HEAD --count'
    return cmd.execute().text.trim().toInteger()
}
static def releaseBuildTime() {
    return new Date().format("yyyy.MM.dd", TimeZone.getTimeZone("UTC"))
}
ext {
    android = [compileSdkVersion: 30,
               applicationId    : "com.xxx.xxx",
               minSdkVersion    : 21,
               targetSdkVersion : 30,
               buildToolsVersion: "30.0.2",
               buildTime        : releaseBuildTime(),
               versionCode      : gitVersionCode(),
               versionName      : "1.x.x"]
}

使用时:

android {
    def android = rootProject.ext.android
    defaultConfig {
        multiDexEnabled true
        minSdk android.minSdkVersion
        compileSdk android.compileSdkVersion
        targetSdk android.targetSdkVersion
        versionCode android.versionCode
        versionName android.versionName
    }
 }

配置你的build

配置不同build类型

在开发中,我们一般会有多个环境,比如 开发环境测试环境线上环境

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    dev{
        // initWith代表的是允许从其他build类型进行复制操作,然后配置我们想更改的设置
        // 这里代表的是从release复制build配置
        initWith release
        // 清单占位符
        manifestPlaceholders = [hostName:"com.petterp.testgradle.dev"]
        // 会在你原包名后面新增.test
        applicationIdSuffix ".dev"
    }
}

如上所述,dev 是我们新增的 build类型 ,当新增之后,我们就可以在命令行使用如下匹配的指令,或者点击As 最右侧,gradle图标,选择app(根据自己build的配置位置而定,一般默认是app-model),选择other,即可看到多了如下几个指令:

网络异常,图片无法展示
|

当然你也可以选择如下命令行执行,以便在 Jenkins 或者 CIbuild 时执行:

gradlew buildDev
gradlew assembleDev

注意,mac下是gradlew开头,windows下可能是./gradlew

配置变体

对于开发中,我们一般都有多渠道的需求,一般而言,如果仅仅是多渠道我们可以选择使用第三方 walle 去做,如果我们可能还有更精细的设置,比如针对这个 build类型,我们很可能对应了不同的默认配置等,比如配置不同的 applicationId ,资源。

如下所示:

// 变体风味名,如果只设置一个,则所有变体会自动使用,如果存在两个及以上,需要在变体中指定,并且变体需要与分组匹配。
// 风味名,类似于风格,分组的意思。
flavorDimensions "channel"
// flavorDimensions ("channel","api")
productFlavors {
    demo1 {
        // 每一个变体都必须存在一个风味,默认使用flavorDimensions(仅限其为单个时)的值,否则如果没提供,则会报错。
        dimension "channel"
        // appid后缀,会覆盖了我们build类型中的applicationIdSuffix
        applicationIdSuffix ".demo"
        // 版本后缀
        versionNameSuffix "-demo"
    }
    demo2 {
        dimension "channel"
        applicationIdSuffix ".demo2"
        versionNameSuffix "-demo2"
    }
}

然后查看我们的 build Variants:

网络异常,图片无法展示
|

Gradle 会根据我们的 变体build类型 自动创建多个build变种,按照 变体名-build类型名 方式命名。

在配置变体时,我们也可以替换在 build类型 中设置的所有默认值,具体原因是,在添加 build类型 时,默认的 defaultConfig 配置其实是属于 ProductFlavors 类,所以我们也可以在任意变体中替换所有默认值。

组合多个变体

在某些场景下,我们可能想将多个产品的变体组合在一起,比如我们想增加一个 api30 的变体,并且针对这个变体,我们想让demo1和demo2与分别也能与其组合在一起 ,即也就是当channel是demo1时api30下对应的包。

理解起来有些拗口,示例如下所示,我们更改上面的配置:

  flavorDimensions("channel", "api")
    productFlavors {
        demo1 {
            dimension "channel"
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
        }
        demo2 {
            dimension "channel"
            applicationIdSuffix ".demo2"
            versionNameSuffix "-demo2"
        }
        minApi23 {
            dimension "api"
            minSdk 23
            applicationIdSuffix ".minapi23"
            versionNameSuffix "-minapi23"
        }
    }

最终如下所示,左侧是 gralde 生成的 build变种 ,右侧对应其中 demo1MinApi23Debug 打包后的产物具体信息:

所以我们可以总结为:

最终我们在打包时,我们的包名和版本名会根据多个变体混合生成,具体如上图所示,然后分别使用了两者都具有的配置,当配置出现重复时,优先以开头的变体配置作为基准。

比如如果我们给demo1变体也配置了最低sdk版本是21,那么最终打出来的包minSdk也会是21,而不是minApi23中的minSdk配置,这点需要注意。

解疑

那么 变体build类型 两者到底应该怎么选?似乎两者好像很是相似?

其实不难理解,如下所示:

比如你新增了一个变体 firDev ,那么默认情况下就会有如下的 build命令 生成

firDevDebug
firDevRelase
firDevXXX(xxx是你自定义的build类型)

需要注意的是 debugrelase 是默认就会存在的,我们可以选择覆盖,否则就算移除,其也会选择默认设置存在

即也就是最终 gradle 会帮我们每个变体都生成相应的 build类型 对应的命令,变体就相当于不同的渠道,而 build类型 就相当于针对这个渠道,存在着多种环境,比如 debug,relase,你自定义的更多build类型。

  • 所以如果你的场景仅仅是想对应几个不同环境,那么直接配置 build类型 即可;
  • 如果你可能希望区分不同的包下的依赖项或者资源配置,那么配置变体即可。
目录
相关文章
|
存储 Java Android开发
Android 开发 - 充分利用Gradle
Android 开发 - 充分利用Gradle
169 2
|
5月前
|
Java API 项目管理
Java一分钟之-Gradle插件开发:自定义构建逻辑
【6月更文挑战第5天】Gradle插件开发详解:从入门到发布。文章介绍如何创建自定义插件,强调依赖管理、任务命名和配置阶段的理解。示例代码展示插件实现及避免常见问题的方法。最后,讨论插件的发布与共享,助你提升构建效率并贡献于开发者社区。动手实践,打造强大Gradle插件!
121 3
|
5月前
|
Android开发
Android Gradle开发—脚本实现自动打包后复制一份APK文件,并修改APK名称,到指定目录作备份
Android Gradle开发—脚本实现自动打包后复制一份APK文件,并修改APK名称,到指定目录作备份
266 0
|
数据安全/隐私保护 Android开发
浅谈build.gradle写法,促使我们更高效开发
浅谈build.gradle写法,促使我们更高效开发
169 0
|
缓存 开发者 Windows
开发这么久,gradle 和 gradlew 啥区别、怎么选?
开发这么久,gradle 和 gradlew 啥区别、怎么选?
开发这么久,gradle 和 gradlew 啥区别、怎么选?
|
XML Java Maven
安卓开发必备——build.gradle文件初探(一)
虽然已经在安卓开发岗位工作了大半年了,但因为作者并没有系统的学习过安卓开发,故基础这块一直都是作者本人的薄弱点,这也是安卓开发必备的由来,希望能填补自己在这方面的缺漏
220 0
|
Shell Android开发
哪怕不学Gradle,这些开发中的常见操作,你也值得掌握(下)
Gradle 是每个 Android 同学都逃不开的一个话题。
222 0
|
Java 开发工具 Android开发
安卓开发必备——build.gradle文件初探(二)
上一篇(安卓开发必备——build.gradle文件初探(一) - 掘金 (juejin.cn))我们探讨了关于安卓项目中最外层目录下的build.gradle,这一篇我们将继续说build.gradle文件
302 0
|
人工智能 移动开发 Java
Android Studio插件版本与Gradle 版本对应关系
Android Studio插件版本与Gradle 版本对应关系
2337 0
Android Studio插件版本与Gradle 版本对应关系
|
1月前
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况