在assembleRelease之前执行自定义任务

背景

在实际的Gradle项目开发中,我们总是会遇到一些需求,要在release编译的时候执行一些任务,但debug时不需要。然而,Gradle编译有自己的一套生命周期,比如Android项目的assembleRelease任务在编译启动之前是没有办法静态获取到的。

下面我们就以“去除release版本中的logcat日志打印”为例,做一个简单的梳理。

源码

修改模板(module)级别的 build.gradle.kts 文件,我们初步目标是在编译刚启动但还没实际开始执行任务时插入我们的自定义任务,切入点就是Gradle的preBuild任务,这个是预定义的,所以可以进行静态配置:

plugins {id("com.android.application")id("kotlin-android")id("kotlin-kapt")
}android {namespace = "com.xxx.yyy"compileSdk = 34// ...
}dependencies {// ...
}// 重点部分
tasks {preBuild {// 编译启动后,相关任务会动态生成,于是可以获取到val isAssembleRelease = gradle.startParameter.taskNames.any {it.contains("assembleRelease")}if (isAssembleRelease) {// 做一些release编译才做的事}}
}

以上可以说就是一个基础模板代码。此外,我们还可以添加本地配置来控制编译任务的开关,在项目(project)级别目录下添加 local.properties 文件,注意这个文件不要添加到git索引中,只是一个本地文件,一般来说项目拉取到本地的时候IDE(如Android Studio)会自动生成此文件:

## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Wed Oct 25 11:29:50 CST 2023
sdk.dir=/Users/xxx/Library/Android/sdk# 增加一个自定义的属性,等会儿使用
BUILD_FOR_RELEASE=true

回去修改模板代码,这样就可以在不需要的时候,关闭自定义任务的执行:

// kts文件头部需要import此类
import java.util.Properties// ...tasks {preBuild {val isAssembleRelease = gradle.startParameter.taskNames.any {// 把app bundle编译也考虑进去it.contains("bundleRelease") || it.contains("assembleRelease")}val localPropsFile = File(project.rootDir, "local.properties")val localProps = localPropsFile.takeIf { it.exists() }?.let {Properties().apply { localPropsFile.inputStream().use { input -> load(input) } }}val toggle = localProps?.getProperty("BUILD_FOR_RELEASE")?.toBoolean() ?: trueif (isAssembleRelease && toggle) {// 做一些release编译才做的事}}
}

接下来,我们开始自定义task,去除release版本中的logcat日志打印:

tasks {val removeLogs by registering {group = "你可以随意定义分组名字,方便在Gradle任务列表中快速查找"doLast {val srcDir = File(project.rootDir, "app/src/main/java")srcDir.walkTopDown().filter {it.isFile && it.extension == "kt"}.forEach {val content = it.readText()it.writeText(content.replace("import android.util.Log", "").replace("Log.", "// Log."))}}}
}

这个任务只是个例子,很简单,目的就是搜寻源码目录下所有的kt文件,然后把logcat相关的代码注释掉。这样可以有效防止被反编译后泄露敏感字符串,当然你可以根据自己的需求随意去修改文件内容。

自定义之后,就是最后一步了,把任务插入添加到Gradle的编译任务链中,主要使用 dependsOn 方法,让preBuild任务依赖于我们的自定义任务:

tasks {val removeLogs by registering {// ...}preBuild {// ...if (isAssembleRelease && toggle) {dependsOn("removeLogs")}}
}

dependsOn 方法还接受多个参数,比如上述若改成 dependsOn("task1", "task2", "task3"),那么在preBuild之前就将按序依次执行这3个task。

记得进行Gradle Sync操作,再启动assembleRelease编译,就可以在构建输出中看到我们自定义的任务了:

Executing tasks: [:app:assembleRelease] in project /Users/xxx/xxx/xxxStarting Gradle Daemon...
Gradle Daemon started in 1 s 244 ms> Configure project :app> Task :app:createReleaseVariantModel UP-TO-DATE
> Task :app:removeLogs
> Task :app:preBuild
> Task :app:preReleaseBuild

可以看到,createReleaseVariantModel这个预定义的任务其实就是在动态生成assembleRelease,然后removeLogs在preBuild的前面,这样就能保证在代码优化和混淆开始之前,对源码进行自定义修改。

补充

对于大多数项目来说,都是有git管理的,所以在我们刚才对源码进行修改之后,其实并不想提交这些修改,而是想在编译完成后撤销修改。那么,我们就可以继续优化上述代码,在assembleRelease完成之后执行简单的git命令:

tasks {val removeLogs by registering {// ...}// 我们可以写一个方法,方便复用fun execGitRollbackAndCleanSrc() {exec { commandLine("git", "checkout", "src") }exec { commandLine("git", "clean", "-fd", "src") }}preBuild {// ...if (isAssembleRelease && toggle) {dependsOn("removeLogs")doLast {findByName("bundleRelease")?.doLast { execGitRollbackAndCleanSrc() }findByName("assembleRelease")?.doLast { execGitRollbackAndCleanSrc() }}}}
}

dependsOn 类似,doLast 也是调整任务链的有效方法之一,即在preBuild执行完成时,动态地给assembleRelease添加一个任务,使得assembleRelease在执行完成时,再执行我们的方法。

后话

上述代码都是一些简单的Gradle脚本,专用于自己项目的一些编译优化,进行大量实践后,完全可以开发成Gradle插件来使用,关键代码都是差不多的,需要的只是熟读Gradle官方文档,了解整个编译构建流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/781087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

下载及安装PHP,composer,phpstudy,thinkPHP6.0框架

文章目录 前言 thinkPHP是一款开源的PHP框架,它是基于MVC(Model-View-Controller)设计模式构建的。thinkPHP提供了丰富的功能和组件,使得开发人员可以快速、高效地构建和维护Web应用程序。 以下是thinkPHP框架的一些特点和功能&…

2023年欧亚地区网络安全态势综述

文 | 中国社会科学院俄罗斯东欧中亚研究所研究员 肖斌;中国社会科学院大学国际政治经济学院研究助理 刘聪 网络安全问题是一个复杂的问题,不仅涉及技术发展,也包含诸多政治色彩。尽管数字空间拉近了互联用户的距离,但是在国际政治…

上位机图像处理和嵌入式模块部署(qmacvisual测量标定)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 在机器视觉中,测量是很重要的一个环节。如果是简单的定位,可能精度要求并不那么严格。但是如果是对产品进行QA测量,需要精确到0.1mm,甚至是0.05mm这样的精度,那就需要对camera…

蓝队面经(一)

蓝队面经(一) 文章目录 蓝队面经(一)入侵排查思路windows入侵排查思路Linux入侵排查思路 Linux 如何查看登录日志Windows 和 Linux 的日志文件放在哪里?WindowsLinux Linux 常用排查命令有哪些?Linux 的 Selinux 是什么?如何设置 Selinux&…

【Leetcode】2952. 需要添加的硬币的最小数量

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接🔗 给你一个下标从 0 0 0 开始的整数数组 c o i n s coins coins,表示可用的硬币的面值,以及一个整数 t a r g e t target target 。 如果存在某个 c o i …

剑指Offer题目笔记21(计数排序)

面试题74: 问题: ​ 输入一个区间的集合,将重叠的区间合并。 解决方案: ​ 先将所有区间按照起始位置排序,然后比较相邻两个区间的结束位置就能知道它们是否重叠。如果它们重叠就将它们合并,然后判断合并…

精选2024年最佳项目管理系统!实用推荐与详细评测

随着企业规模的扩大,项目量也会呈几何倍的增长,项目管理系统就成了企业管理必不可少的一部分。2024年优秀的项目管理系统推荐。今年为大家带来Microsoft Project、Zoho Projects、Jira以及Wrike项目管理系统评测。 什么是项目管理系统? 项目…

怎么更新sd-webui AUTOMATIC1111/stable-diffusion-webui ?

整个工程依靠脚本起来的: 可直接到stable-diffusion-webui子目录执行: git pull更新代码完毕后,删除venv的虚拟环境。 然后再次执行webui.sh,这样会自动重新启动stable-diffusion-webui.

springboot心灵治愈交流平台

摘 要 本论文主要论述了如何使用JAVA语言开发一个心灵治愈交流平台 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述心灵治愈交流平台的当前背景以及系统开发的…

代码随想录算法训练营第三十二天|leetcode738题

一、leetcode第738题 本题要求返回小于等于给定数字且从最高位到最低位呈单调递增的数值,需要从最低位向最高位遍历,如果最低位比其前一位小则若要使改变后数值最大需要将前一位作减一操作并记录下当前位,在遍历结束后将记录的当前位之后的所…

啥是MCU,MCU科普

啥是MCU,MCU科普 附赠自动驾驶学习资料和量产经验:链接 MCU是Microcontroller Unit 的简称,中文叫微控制器,俗称单片机,是把CPU的频率与规格做适当缩减,并将内存、计数器、USB、A/D转换、UART、PLC、DMA等…

Leetcode 42.接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#x…

多线程(19)活锁和线程饥饿

活锁(Livelock)和线程饥饿(Thread Starvation)是并发编程领域中两个至关重要且常见的问题。理解这两个概念,以及它们如何影响程序的执行和系统的性能,对于开发能够有效并行处理任务的应用程序至关重要。 1…

发表SCI论文对作者学位职位有要求吗?

SCI论文是被SCI(Scientific Citation Index,《科学引文索引》)收录的期刊所刊登的论文。能够在SCI上成功发表论文是证明作者的一定的能力被国际研究界所认可,国内的很多科研人员因此对其也是非常向往的。 那么发表SCI论文对作者学位职位有要求吗? 通常…

基于单片机智能输液器监控系统的设计

**单片机设计介绍,基于单片机智能输液器监控系统的设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机智能输液器监控系统的设计旨在实现对输液过程的实时监测和控制,以提高输液的安全性和疗效…

香港服务器与SEO的关系(香港服务器对SEO影响大吗?)

香港服务器与 SEO 的关系是一个备受关注的话题,不少站长在选择了香港服务器后,便会疑问:香港服务器对SEO的影响是否显著?那么,在这里就跟大家聊聊两者的关系以及影响大小。 其实,不少站长对 SEO 的这种担忧和想法是片…

发生播放错误,即将重试 jellyfin

上周在家里的小主机上部署了jellyfin,真香,手机安卓端使用无问题,于是今天准备在电视上安装一个 首先是直接安装的手机版客户端,操作卡顿,而且很多操作没法实现,于是去下了一个tv版本 安装上后发现&#…

R语言数据分析基础(一)

在R中,读取和操作Excel文件最常用的readxl包,可以读取Excel文件,writexl包可以写入Excel文件。以下是常见的操作: 安装和加载包 首先,需要安装和加载readxl和writexl包。 install.packages("readxl") ins…

InternLM2-lesson1

书生浦语大模型全链路开源体系 课程视频:https://www.bilibili.com/video/BV1Vx421X72D/ 开源历程 全面开源,免费商用!!! internlm2模型体系 internlm2根据参数量可以分为7B和20B两个大的版本,每个大的…

Kubernetes篇(二)— 集群环境搭建

目录 前言一、 环境规划集群类型安装方式主机规划 二、环境搭建主机安装环境初始化安装docker安装kubernetes组件准备集群镜像集群初始化安装网络插件 三、 服务部署 前言 本章节主要介绍如何搭建kubernetes的集群环境 一、 环境规划 集群类型 kubernetes集群大体上分为两类…