当前位置: 首页 > news >正文

如何共享 Android 不同模块的构建配置

最近想重新梳理学习一遍 Android 的各个知识点,于是新建了一个 AndroidStudy 项目仓库,打算每个知识块新建 1 个 module。
类似这样:

AndroidStudy (Root Project)
├─app (Module0)
├─CustomView (Module1)
├─KotlinCoroutines (Module2)
├─...

然后发现每新建 1 个 Android Library Module 都生成 1 个新的 build.gradle.kts 文件

plugins {alias(libs.plugins.com.android.library)alias(libs.plugins.org.jetbrains.kotlin.android)
}android {namespace = "com.bqliang.mylibrary"compileSdk = 33defaultConfig {minSdk = 26testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"consumerProguardFiles("consumer-rules.pro")}buildTypes {release {isMinifyEnabled = falseproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}compileOptions {sourceCompatibility = JavaVersion.VERSION_1_8targetCompatibility = JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = "1.8"}
}dependencies {implementation(libs.core.ktx)...
}

里面的大部分配置都是重复的,像 compileSdk、minSdk、compileOptions、kotlinOptions… 虽然我以后也不会再去改这些配置了,但是代码洁癖还是让我想把这些重复的配置去掉,经过一番搜索,发现 Gradle Convention Plugin 非常适合解决这个问题。

什么是 Gradle Convention Plugin

为了解决上面的问题,我们自然很容易想到要把其中可以共享的配置抽取出来,然后在每个 module 中引用这些配置。我们可以编写 1 个预编译插件 AndroidLibraryPlugin,在其中去处理这些共享的构建逻辑,然后在需要的 module 中引用这个插件。这样就可以避免重复的配置了,这样的插件就叫做 Gradle Convention Plugin,所以 Gradle Convention Plugin 并不是指某个具体的插件(像 com.android.library),而是指一类插件,这类插件的作用就是抽取出一些共享的构建逻辑。

如何编写 Gradle Convention Plugin

提到预编译插件,很多人知道可以写在 buildSrc 目录下,但是这种方式还是有一些缺点的,比如任何更改都会导致整个项目重新编译,更好的方式是使用复合构建(composite build)

我们新建 1 个 build-logic 项目,文件结构如下,我们将在 AndroidLibraryConventionPlugin 中编写我们的要在 Android Library Module 中共享的构建逻辑。

AndroidStudy (Root Project)
├─...
└─build-logic|  settings.gradle.kts└─ convention|  build.gradle.kts└─ src└─ main└─ kotlin└─ AndroidLibraryConventionPlugin.kt

因为复合构建项目里的构建是完全独立的,所以我们需要在 build-logic/settings.gradle.kts 中声明依赖仓库源,也要显式声明 versionCatalogs

dependencyResolutionManagement {repositories {google()mavenCentral()}versionCatalogs {create("libs") {from(files("../gradle/libs.versions.toml"))}}
}rootProject.name = "build-logic"
include(":convention")

build-logic/convention/build.gradle.kts:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompileplugins {`kotlin-dsl`
}group = "com.bqliang.gradleconventionplugins.buildlogic"// Configure the build-logic plugins to target JDK 17
// This matches the JDK used to build the project, and is not related to what is running on device.
java {sourceCompatibility = JavaVersion.VERSION_17targetCompatibility = JavaVersion.VERSION_17
}
tasks.withType<KotlinCompile>().configureEach {kotlinOptions {jvmTarget = JavaVersion.VERSION_17.toString()}
}dependencies {compileOnly(libs.android.gradlePlugin)compileOnly(libs.kotlin.gradlePlugin)
}gradlePlugin {// register the convention pluginplugins {register("androidLibrary") {id = "bqliang.android.library"implementationClass = "AndroidLibraryConventionPlugin"}}
}

这里的 sourceCompatibility、targetCompatibility、kotlinOptions 只是用来指定编译我们的 Gradle Convention Plugin 的 JDK 版本,和共享的构建逻辑没有关系。文件最后注册了我们的 Gradle Convention Plugin,为了后续方便引用,我们可以把 plugin id 写在 libs.versions.toml 里:

...
[plugins]
bqliang-android-library = { id = "bqliang.android.library", version = "unspecified" }
...

build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt:

import com.android.build.api.dsl.CommonExtension
import com.android.build.gradle.LibraryExtension
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileclass AndroidLibraryConventionPlugin : Plugin<Project> {override fun apply(target: Project) {with(target) {with(pluginManager) {// Android Library Module 都需要这 2 个插件apply("com.android.library")apply("org.jetbrains.kotlin.android")}extensions.configure<LibraryExtension> {configureKotlinAndroid(this)defaultConfig.targetSdk = 34}}}private fun Project.configureKotlinAndroid(commonExtension: CommonExtension<*, *, *, *, *>,) {commonExtension.apply {compileSdk = 34defaultConfig {minSdk = 26}compileOptions {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11}}configureKotlin()}private fun Project.configureKotlin() {// Use withType to workaround https://youtrack.jetbrains.com/issue/KT-55947tasks.withType<KotlinCompile>().configureEach {kotlinOptions {// Set JVM target to 11jvmTarget = JavaVersion.VERSION_11.toString()}}}
}

注意,目前我们还没有在 root project 中 include 这个 build-logic 项目呢,因为复合构建会把项目里的构建配置包含进来,所以我们不能直接使用 include(“:build-logic”),而是要使用 includeBuild(“build-logic”)

AndroidStudy/settings.gradle.kts:

pluginManagement {includeBuild("build-logic") // include build-logic modulerepositories {google()mavenCentral()gradlePluginPortal()}
}dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()}
}rootProject.name = "AndroidStudy"
...

现在我们就可以使用我们的预编译约定插件 AndroidLibraryConventionPlugin 了,回到文章一开始那个 Android Library Module 的 build.gradle.kts,我们可以把里面的大部分配置都去掉了,只是简单的引用一下我们的插件就可以了。

plugins {alias(libs.plugins.bqliang.android.library) // apply our convention plugin
}android {namespace = "com.bqliang.mylibrary"defaultConfig {testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"consumerProguardFiles("consumer-rules.pro")}buildTypes {release {isMinifyEnabled = falseproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}
}dependencies {...
}

当然这里只是把 Android Library Module 的构建逻辑抽取出来了,其实像 Application Module、Jetpack Compose、Room 等等构建逻辑都是可以抽取出来的。

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap

相关文章:

如何共享 Android 不同模块的构建配置

最近想重新梳理学习一遍 Android 的各个知识点&#xff0c;于是新建了一个 AndroidStudy 项目仓库&#xff0c;打算每个知识块新建 1 个 module。 类似这样&#xff1a; AndroidStudy (Root Project) ├─app (Module0) ├─CustomView (Module1) ├─KotlinCoroutines (Modul…...

atlas运维中遇到的问题

1、java.lang.NoClassDefFoundError&#xff1a;javax/ws/rs/core/Link$Builder 主要原因&#xff1a;jsr311-api包中javax.ws.rs.core包中没有Link类&#xff0c;而Atlas以HBase作为元数据存储&#xff0c;HBase本身使用的为javax.ws.rs-api包中的core包&#xff0c;其中有Lin…...

06-React的路由

06-React的路由 1.相关理解 1).SPA的理解 单页Web应用&#xff08;single page web application&#xff0c;SPA&#xff09;。整个应用只有一个完整的页面。点击页面中的链接不会刷新页面&#xff0c;只会做页面的局部更新。数据都需要通过ajax请求获取, 并在前端异步展现。…...

虹科方案 | 加州理工学院利用HK-TrueNAS开展地震研究

一、客户背景 加州理工学院(CalTech)是世界顶尖的理工类科学研究型学府之一。加州理工学院地震实验室是加州理工学院地质与行星科学部(GPS)的一个分支机构&#xff0c;成立于1921年&#xff0c;自20年代以来一直是世界地震学研究中心&#xff0c;并且几十年来一直是媒体对大地…...

宝塔面板部署express以及MySql项目

第一次在宝塔面板上部署express和MySql项目&#xff0c;部署过程一直跑不通接口&#xff0c;特此记录一下。 在部署的时候&#xff0c;建议第一步把数据库MySql给跑通&#xff0c;中间好多原因是由于数据库的原因给引起的。 一.连接数据库 &#xff08;1&#xff09;在宝塔面…...

联盟链学习笔记-网络的创建

联盟链学习笔记 初始网络 下图是初始网络网络N的参考图 排序服务 在定义 网络 N 的时候&#xff0c;第一件事情就是定义一个 排序服务O4。O4 最初被配置并且由组织 R4 的一个管理员来启动&#xff0c;并且由 R4 管理。配置 NC4 包含了描述网络管理能力初始集合的规则。最初在…...

System.Drawing.Common.Bitmap跨平台的替代方案

使用SkiaSharp SkiaSharp是Skia Graphics Library的.Net跨平台实现&#xff0c;它可以在Windows&#xff0c;macOS&#xff0c;Linux&#xff0c;iOS&#xff0c;Android和其他平台上使用。 例如需要Linux版&#xff0c;则安装第一个和第四个&#xff1a; 以下是使用SkiaShar…...

深入理解 Java 泛型

没有泛型是怎样的 了解点 Java 历史的都知道,泛型是从 JDK 1.5 版本添加的特性,在 JDK1.5 之前,Java 很多特性都是没有的例如:泛型、注解、自动装箱和拆箱、可变参数。在介绍泛型之前,我们先来看看,如果没有泛型的世界是怎么样的。 假设有一个 List,我只想把 String 类…...

【基础篇】七、Flink核心概念

文章目录 1、并行度2、并行度的设置3、算子链4、禁用算子链5、任务槽6、任务槽和并行度的关系 1、并行度 要处理的数据量很多时&#xff0c;可以把一个算子的操作&#xff08;比如前面demo里的flatMap、sum&#xff09;&#xff0c;"复制"多份到多个节点&#xff0c…...

06-Scala面向对象

面向对象编程 ​ Scala是一门完全面向对象的语言&#xff0c;摒弃了Java中很多不是面向对象的语法。 ​ 虽然如此&#xff0c;但其面向对象思想和 Java的面向对象思想还是一致的 Scala包 1&#xff09;基本语法 Scala中基本的package包语法和 Java 完全一致 例如&#xf…...

【设计模式】单例模式、“多例模式”的实现以及对单例的一些思考

文章目录 1.概述2.单例模式实现代码2.1.饿汉式单例2.2.懒汉式单例2.3.双检锁单例2.4.静态内部类单例2.5.枚举单例 3.对单例的一些思考3.1.是否需要严格的禁止单例被破坏&#xff1f;3.2.懒汉式真的比饿汉式更佳吗&#xff1f;3.3.单例存在的问题 4.其他作用范围的单例模式4.1.线…...

idea 2022 一个工作空间下导入git项目 后 无法导入第二个git项目

idea 2022 一个工作空间下导入git项目 后 无法导入第二个git项目 如图所示 我导入了一个git项目后&#xff0c;菜单栏出现了一个git按钮 找不到 导入git项目的按钮了 方式1、 通过idea设置 打开全局设置 如下图 把git先改为none&#xff0c;保存 保存后就可以看到 VCS按钮 导入…...

泛在电力物联网的关键技术与未来发展策略-安科瑞黄安南

摘要: 文章分析了泛在电力物联网的内涵及其主要特征&#xff0c;针对泛在电力物联网的建设目标、基本构架以及关键技术与未来发展策略进行综合探讨&#xff0c;期待得到专业人士的指点。 关键词: 泛在电力物联网&#xff0c; 网络规划&#xff0c; 网络发展 随着能源革命的不…...

iWall:支持自定义的Mac动态壁纸软件

iWall Mac是一款动态壁纸软件&#xff0c;它可以使用任何格式的漂亮视频&#xff08;无须转换&#xff09;、图片、动画、Flash、gif、swf、程序、网页、网站做为您的动态壁纸、动态桌面&#xff0c;并且可以进行交互。 这款软件功能多、使用简单、体积小巧、不占用资源、运行…...

【Docker 内核详解】namespace 资源隔离(四):Mount namespace Network namespace

【Docker 内核详解 - namespace 资源隔离】系列包含&#xff1a; namespace 资源隔离&#xff08;一&#xff09;&#xff1a;进行 namespace API 操作的 4 种方式namespace 资源隔离&#xff08;二&#xff09;&#xff1a;UTS namespace & IPC namespacenamespace 资源隔…...

STM32简介

STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器&#xff0c;常应用在嵌入式领域如&#xff1a; 智能车&#xff08;用stm32做寻迹小车&#xff0c;读取光电传感器或者摄像头数据&#xff0c;然后驱动电机前进和转弯&#xff09;&#xff1b; 无人机&#xff08;用stm3…...

Yum安装JDK11

一、安装命令 &#xff1a; yum install java-11-openjdk二、执行以下命令来查看 JDK 11 的安装信息&#xff1a; yum list installed | grep java-11-openjdk三、找到 JDK 11 的软件包名称&#xff08;使用以下命令来查询软件包的安装位置&#xff09;&#xff1a; rpm -ql…...

[HNCTF 2022 WEEK2]ez_ssrf题目解析

这题主要是引入ssrf这个漏洞攻击&#xff0c;本质上没有更深入的考察 本题是需要我们去伪造一个ssrf的请求头去绕过 题目开始给了我们信息让我们去访问index.php fsockopen函数触发ssrf fsockopen() 函数建立与指定主机和端口的 socket 连接。然后&#xff0c;它将传入的 bas…...

OpenFOAM: twoPhaseEulerFoam解读

twoPhaseEulerFoam全解读之一(转载) 本系列将对OpenFOAM-2.1.1 中的 twoPhaseEulerFoam 求解器进行完全解读&#xff0c;共分三部分&#xff1a;方程推导&#xff0c;代码解读&#xff0c;补充说明。本篇进行方程推导&#xff0c;详细介绍如果从双流体模型出发得到 twoPhaseEu…...

ffmpeg跨平台arm编译-ubuntu

目录 1. 安装必要的编译器2. 安装必要的依赖项3. 配置编译选项4. 编译安装 1. 安装必要的编译器 32位系统&#xff1a; sudo apt-get update sudo apt-get install gcc-arm-linux-gnueabihf sudo apt-get install g-arm-linux-gnueabihf64位系统&#xff1a; sudo apt-get u…...

Vue 网络处理 - axios 异步请求的使用,请求响应拦截器

目录 一、axiox 1.1、axios 简介 1.2、axios 基本使用 1.2.1、下载核心 js 文件. 1.2.2、发送 GET 异步请求 1.2.3、发送 POST 异步请求 1.2.4、发送 GET、POST 请求最佳实践 1.3、请求响应拦截器 1.3.1、拦截器解释 1.3.2、请求拦截器的使用 1.3.3、响应拦截器的使用…...

单目3D目标检测——MonoDLE 模型训练 | 模型推理

本文分享 MonoDLE 的模型训练、模型推理、可视化3D检测结果。 模型原理&#xff0c;参考我这篇博客&#xff1a;【论文解读】单目3D目标检测 MonoDLE&#xff08;CVPR2021&#xff09;_一颗小树x的博客-CSDN博客 源码地址&#xff1a;https://github.com/xinzhuma/monodle 目…...

CSS悬停卡片翻转明信片效果源码附注释

运行效果演示: HTML页面代码: <!DOCTYPE html> <html lang="en" > <head>...

使用kaliber与imu_utils进行IMU、相机+IMU联合标定

目录 1 标定工具编译 1.1 IMU标定工具 imu_utils 1.2 相机标定工具 kaliber 2 标定数据录制 3 开始标定 3.1 IMU标定 3.2 相机标定 3.3 相机IMU联合标定 4 将参数填入ORBSLAM的文件中 1 标定工具编译 1.1 IMU标定工具 imu_utils 标定IMU我们使用imu_utils软件进行标定…...

统一观测丨使用 Prometheus 监控 SQL Server 最佳实践

作者&#xff1a;啃唯 SQL Server 简介 SQL Server 是什么&#xff1f; Microsoft SQL Server 是 Microsoft 推出的关系型数据库解决方案&#xff0c;支持企业 IT 环境中的各种事务处理、商业智能和分析应用程序。Microsoft SQL Server 是市场领先的数据库技术之一。 SQL S…...

最短无序连续子数组

题目链接 最短无序连续子数组 题目描述 注意点 找出符合题意的 最短 子数组&#xff0c;并输出它的长度-100000 < nums[i] < 100000 解答思路 本题的数组可以分为三段&#xff0c;左段中段和右段&#xff0c;如下图所示 观察规律可知&#xff0c;左段元素始终比中段…...

更新 | 持续开源迅为RK3568驱动指南第十二篇-GPIO子系统

《iTOP-RK3568开发板驱动开发指南》更新&#xff0c;本次更新内容对应的是驱动&#xff08;第十二期_GPIO子系统-全新升级&#xff09;视频&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 文档教程更新至第十…...

centos7安装erlang23.3.4.11及rabbitmq3.9.16版本

rpm包有系统版本要求&#xff0c;el是Red Hat Enterprise Linux(EL)的缩写。 EL7是Red Hat 7.x&#xff0c;Centos 7.x EL8是Red Hat 8.x, Centos 8.x 所以我们在安装erlang及rabbitmq时需要选择与自己的服务器相对应的rpm包 # rabbitmq的rpm安装包 https://github.com/rabbi…...

VMware和Debian下载

文章目录 ⭐️写在前面的话⭐️一、VMware二、Debain三、建立虚拟机&#x1f680; 先看后赞&#xff0c;养成习惯&#xff01;&#x1f680;&#x1f680; 先看后赞&#xff0c;养成习惯&#xff01;&#x1f680; ⭐️写在前面的话⭐️ CSDN主页&#xff1a;程序员好冰 目前在…...

mysql面试题48:MySQL中 Innodb的事务与日志的实现方式

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官: Innodb的事务与日志的实现方式 以下是InnoDB事务和日志的实现方式的详细说明: 事务日志(Transaction Log): InnoDB使用事务日志来保证事务的…...

wordpress contactform/全球搜索引擎

结构体数组在颜色存储中的使用 什么是结构体数组&#xff1f; 结构体数组就是数组&#xff0c;用来装结构体变量的&#xff0c;那什么是结构体变量呢&#xff1f;结构体变量是用结构体类型定义的变量&#xff0c;那什么是结构体类型呢&#xff1f;如果不清楚你可移步往期文章…...

个人网站的作用/济南网站建设哪家好

房地产是支柱产业占GDP的比重很高 房地产是民生产业&#xff0c;老百姓的财富&#xff0c;60%在房地产&#xff0c;也该稳定&#xff1b; 房地产是半金融产业&#xff0c;大量的按揭贷款&#xff0c;它崩盘的话&#xff0c;对金融机构也是问题&#xff1b; 房地产还和大量的供应…...

甘肃工程造价信息网/深圳seo优化推广

用dos命令创建别人无法进入又无法删除的文件夹 发布时间&#xff1a;2009.10.22 新闻来源&#xff1a;大连华育国际软件培训校区-大连JAVA培训,大连软件培训,大连华育国际,大连.net工程师培训,大连定单培训,就业实训,大连IT教育培训,大连软件人才 浏览次数&#xff1a;7 第一步…...

可以做旅行计划的网站/网络宣传

当我们平时清理电脑文件时误删了文件&#xff0c;而想要恢复误删文件就不知道怎么处理了。下面与大家分享用diskgenius分区工具来恢复删除文件&#xff0c;一起来看看如何 恢复文件 吧。1、首先&#xff0c;我们提前制作好u启动u盘启动盘。接着将该u盘启动盘插入电脑usb接口&am…...

大学 建网站/毕节地seo

关于二叉排序树的定义以及如何查找指定关键字的结点不再赘述&#xff0c;本篇文章主要讨论二叉排序树如何删除一个指定的结点。 当我们利用查找算法在树中找到了对应的结点的时候&#xff0c;可能会遇到三类情况。 第一类情况&#xff1a; 即将删除的结点是叶结点&#xff0…...

便宜网站建设 优帮云/2022年新闻摘抄简短

了解一个百万级 PHP 网站的架构 Poppen.de 是德国的一个社交网站&#xff0c;相对Facebook、Flickr来说是一个很小的网站&#xff0c;但它有一个很好的架构&#xff0c;融合了很多技术&#xff0c;如 Nigix、MySql、CouchDB、Erlang、Memcached、RabbitMQ、PHP、Graphite、Red5…...