【Android gradle】自定义一个android gradle插件之buildSrc

news2024/12/24 20:28:02

文章目录

  • 1. 前言
  • 2. 简单使用
  • 3. 其余用法
    • 3.1 依赖&版本管理
    • 3.2 插件版本自增
    • 3.3 其余
  • 4. 链接

1. 前言

在【Android gradle】自定义一个android gradle插件,并发布到私有Artifactory仓库这篇文章中介绍了定义一个gradle插件,然后发布到远程或者本地仓库,最后在项目中使用的流程。但实际上还是过于复杂化了。对于自己的项目工程来说,我们希望简化这个流程,而buildSrc这个目录就运应而生了。

2. 简单使用

在项目目录下执行下面的操作:

# 1. 创建buildSrc目录,当然也可以用下面的命令来创建多个
mkdir buildSrc

首先,根据你自己期望的java或者groovy语言来创建目录:

# 2. 插件源代码目录
mkdir buildSrc\src\main\java

然后同步一下项目,可以看见这个目录就被识别了:
在这里插入图片描述
然后在其下创建对应的Plugin实现类以及对应的Task,比如:

public class HelloPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {
        project.getTasks().create("firstTask", FirstTask.class);
    }
}

public class FirstTask extends DefaultTask {

    @TaskAction
    void doSomething() {
        getProject().getLogger().warn("=========> firstTask:doSomething...");
    }
}

然后,类似的我们需要在resources目录下创建META-INF/gradle-plugins两级目录,然后创建对应的自己定义的插件名.properties文件(完整路径:buildSrc/src/main/resources/META-INF/gradle-plugins/sample.properties),其中做关联:

implementation-class=com.mengfou.HelloPlugin

最后就是在我们的项目的build.gradle中进行apply

apply plugin: 'com.mengfou.HelloPlugin'

再次同步后,就可以看到我们定义的firstTask
在这里插入图片描述
最后可以通过执行这个task来看看是否定义成功:

gradlew firstTask

在这里插入图片描述

可以看见就执行了。而且这个过程中我们并没有添加:

import org.gradle.api.Plugin;
import org.gradle.api.Project;

等相关的依赖,这里却可以很方便的使用,较上一篇文中的定义插件的方式确实方便了很多。

3. 其余用法

3.1 依赖&版本管理

比如我们可以使用buildSrc来管理依赖,比如我们可以定义一个Deps.java的文件来进行依赖的版本管理,在这个新建的demo工程的app模块的build.gradle文件中有这些依赖:

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

我们可以将其进行改造,即:

public class Deps {
    public static final String appCompat = "androidx.appcompat:appcompat:1.3.0";
    public static final String material = "com.google.android.material:material:1.4.0";
    public static final String constraintLayout = "androidx.constraintlayout:constraintlayout:2.0.4";
    public static final String junit = "junit:junit:4.13.2";
    public static final String ext_junit = "androidx.test.ext:junit:1.1.3";
    public static final String espresso = "androidx.test.espresso:espresso-core:3.4.0";
}

然后同步一下,最终我们在build.gradle中可直接导包后使用:

import com.mengfou.deps.Deps
dependencies {
    implementation Deps.appCompat
    implementation Deps.material
    implementation Deps.constraintLayout
    testImplementation Deps.junit
    androidTestImplementation Deps.ext_junit
    androidTestImplementation Deps.espresso
}

3.2 插件版本自增

为了更方便的管理(自增)发布插件/aar/apk的版本,我们可以写一个插件做一个简单的版本管理。可以简单定义一个修改文件名的Task

public class ApkVersionTask extends DefaultTask {
    private Project mProject;
    private String mVariant;

    @TaskAction
    public void modifyFileName() {
        AppExtension appExtension = mProject.getExtensions().getByType(AppExtension.class);
        for (ApplicationVariant applicationVariant : appExtension.getApplicationVariants()) {
            if(mVariant.equals(applicationVariant.getName())) {
                try {
                    String stringBuilder = mProject.getBuildDir().getAbsolutePath() +
                            File.separator +
                            "outputs" +
                            File.separator +
                            "apk" +
                            File.separator +
                            applicationVariant.getBuildType().getName();
                    File parent = new File(stringBuilder);
                    for (File file : Objects.requireNonNull(parent.listFiles())) {
                        if (file.getName().endsWith(".apk")) {
                            File outputNewFile = new File(parent, "mengfou-" + getConfigVersion() + "-" + mVariant.toLowerCase() + ".apk");
                            file.renameTo(outputNewFile);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private String getConfigVersion() {
        try {
            File file = new File(mProject.getBuildFile().getParent(), "versions.properties");
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int len = -1;
            StringBuilder stringBuffer = new StringBuilder();
            while((len = fileInputStream.read(buffer)) != -1) {
                stringBuffer.append(new String(buffer, 0, len));
            }
            if(stringBuffer.toString().trim().length() != 0) {
                String[] split = stringBuffer.toString().split("=");
                if(split.length == 2 && split[0].equals("apk-version")) {
                    return split[1];
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "empty";
    }

    public void setProject(Project project) {
        mProject = project;
    }

    public void setVariant(String variant) {
        mVariant = variant;
    }
}

getConfigVersion为从app/versions.properties文件中读取一个apk-version的配置,即:

apk-version=1.2.0

然后我们需要做的就是将ApkVersionTask插入到插件的合适的位置中去,通过命令:

>gradlew assemDeb --console=plain --stacktrace

可以看见最终执行的task

> Task :app:packageDebug
> Task :app:createDebugApkListingFileRedirect
> Task :app:assembleDebug

所以我们只需要将自定义的Task放置在packageDebug之后,assembleDebug之前即可。

public class HelloPlugin implements Plugin<Project> {

    @Override
    public void apply(Project project) {
        AppExtension appExtension = project.getExtensions().getByType(AppExtension.class);
        project.afterEvaluate(new Action<Project>() {
            @Override
            public void execute(Project project) {
                for (ApplicationVariant applicationVariant : appExtension.getApplicationVariants()) {
                    System.out.println("applicationVariant is: " + applicationVariant.toString());
                    try {
                        ApkVersionTask apkVersionTask = project.getTasks().create(getTaskName("reName", "Apk", applicationVariant.getName()), ApkVersionTask.class);
                        apkVersionTask.setProject(project);
                        apkVersionTask.setVariant(applicationVariant.getName());

                        Class<? extends ApplicationVariantImpl> aClass = ((ApplicationVariantImpl) applicationVariant).getClass();
                        Method variantData = aClass.getDeclaredMethod("getVariantData");
                        variantData.setAccessible(true);
                        BaseVariantData baseVariantData = (BaseVariantData) variantData.invoke(applicationVariant);

                        Task packageTask = project.getTasks().findByName(baseVariantData.getTaskContainer().getPackageAndroidTask().getName());
                        Task createApkListingFileRedirectTask = project.getTasks().findByName(getTaskName("create", "ApkListingFileRedirect", applicationVariant.getName()));
                        apkVersionTask.dependsOn(packageTask);
                        apkVersionTask.dependsOn(createApkListingFileRedirectTask);
                        Task assembleTask = project.getTasks().findByName(getTaskName("assemble", "", applicationVariant.getName()));
                        assembleTask.dependsOn(apkVersionTask);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    public String getTaskName(String prefix, String suffix, String variantName) {
        String name = variantName.substring(0, 1).toUpperCase() + variantName.substring(1);
        return prefix + name + suffix;
    }

}

运行后:
在这里插入图片描述
可以看见达到了预期。

3.3 其余

待填坑…

4. 链接

代码地址:https://gitee.com/weizu_cool/gradle-plugin-demo.git

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

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

相关文章

对数据库索引和事务的理解

1.数据库授权命令&#xff1a; GRANT<权限> on 表名(或列名) to 用户。 举例&#xff1a; 授予用户SQLTest对数据库Sales的CUSTOMERS表的列cid、cname的查询权限 grant select on CUSTOMERS(cid,cname) to SQLTest; 2.MySQL索引&#xff08;index&#xff09; 什么是索引…

C++5:初见模板

目录 函数模板 函数模板的实例化&#xff1a; 隐式实例化 显示实例化 类模板 虽然学习了类和对象&#xff0c;能很方便的处理一些容器类的问题&#xff0c;但是我们还是会遇到如下这种情况。 我们创建一个简单的stack类 class Stack { public:Stack(){} private:int* _a;…

【机器学习】Logistic Regression 逻辑回归算法详解 + Java代码实现

文章目录一、逻辑回归简介1.1 什么是逻辑回归1.2 Sigmoid函数1.3 预测函数二、逻辑回归实战 - Java代码实现一、逻辑回归简介 1.1 什么是逻辑回归 逻辑回归&#xff08;Logistic Regression&#xff09;是一种用于解决二分类&#xff08;0 or 1&#xff09;问题的机器学习方法…

时间序列模型SCINet模型(自定义项目)

前言 读完代码解析篇&#xff0c;我们针对开源项目中的模型预测方法做一下介绍。Github源码下载地址下载数据集ETTh、PEMS、Traffic、Splar-Energy、Electricity、Exchange-Rate&#xff0c;这几类公共数据集的任意一类就行。这里以ETTh数据集为例&#xff0c;先在项目文件夹下…

whistle抓包工具应用

原文地址&#xff1a;(67条消息) whistle抓包工具学习_BBC蟹耳总的博客-CSDN博客_w2 抓包 一、安装whistle 首先安装好whistle抓包工具&#xff0c;有以下两个步骤 在终端中全局安装whistle&#xff1a;npm install -g whistle可以通过whistle help查看相关信息&#xff0c;…

《零基础学机器学习》读书笔记一

《零基础学机器学习》读书笔记一 一、机器学习快速上手路径 1.1 机器学习的家族谱 人工智能&#xff0c;可以被简单地定义为努力将通常由人类完成的智力任务自动化。 AI效应的2个阶段&#xff1a; &#xff08;1&#xff09;AI将新技术、新体验带进人类的生活&#xff0c;完…

linux环境安装mysql5.7版本

目录 一、下载准备阶段 二、安装运行阶段 linux环境安装mysql是我们工程师必备的技能之一&#xff0c;今天我们实战分享一下安装流程&#xff1a; 一、下载准备阶段 1、查看linux系统是否已经安装mysql rpm -qa|grep -i mysql 显示没有 如果安装过&#xff0c;可以删除&…

DFS排列组合与连通性

目录 一、前言 二、DFS与排列组合 1、DFS&#xff1a;自写排列算法1 &#xff08;1&#xff09;基础模板 &#xff08;2&#xff09;基于(1)输出前n个数任意m个都全排列 2、DFS&#xff1a;自写排列算法2&#xff08;这个写法更常见&#xff09; &#xff08;1&#xff…

Java安装详细教程

这里写自定义目录标题Java安装详细教程1.下载Java2&#xff0c;找到jdk8进行下载3.安装jdk4.配置环境变量5.查看是否已经成功安装Java安装详细教程 换了新电脑了&#xff0c;需要安装Java&#xff0c;如果对你也有帮助就点个赞吧~~ 文章目录Java安装详细教程1.下载Java2&#…

一阶低通滤波器学习

导读&#xff1a;电压型磁链观测器由于物理概念清晰、简单易用而备受关注。然而电压型磁链观测器包含一纯积分项&#xff0c;被积项的初始相位与直流偏置都会影响积分结果。所以对传统电压型磁链观测器的改进措施有很多&#xff0c;本期文章主要介绍采用一阶低通滤波器来替换掉…

Java程序设计实验2 | Java语言基础

*本文是博主对Java各种实验的再整理与详解&#xff0c;除了代码部分和解析部分&#xff0c;一些题目还增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人自己的补充&#xff0c;以方便大家额外学习、参考。 目录 一、实验…

微信小程序使用npm包、全局数据共享和分包

文章目录导航路线使用 npm 包小程序对 npm 的支持与限制Vant Weapp1. 什么是 Vant Weapp2. 安装 Vant 组件库3. 使用 Vant 组件4. 定制全局主题样式5. 定制全局主题样式API Promise化1. 基于回调函数的异步 API 的缺点2. 什么是 API Promise 化3. 实现 API Promise 化4. 调用 P…

鸣人的影分身(动态规划 | DP | 整数划分模型)[《信息学奥赛一本通》]

题目如下&#xff1a; 在火影忍者的世界里&#xff0c;令敌人捉摸不透是非常关键的。 我们的主角漩涡鸣人所拥有的一个招数——多重影分身之术——就是一个很好的例子。 影分身是由鸣人身体的查克拉能量制造的&#xff0c;使用的查克拉越多&#xff0c;制造出的影分身越强。…

6.R语言【频数、频率统计函数】一维、二维、三维

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff0c;有点废话&#xff09;&…

PostgreSQL数据库FDW——Parquet S3 MultifileMergeExecutionStateBaseS3

MultifileMergeExecutionStateBaseS3和SingleFileExecutionStateS3、MultifileExecutionStateS3类不同&#xff0c;reader成员被替换为ParquetReader *类型的readers vector。新增slots_initialized布尔变量指示slots成员是否已经初始化。slots成员是Heap类&#xff0c;Heap用于…

重装系统Windows10纯净版操作步骤(微pe)

目录 前言 操作步骤 第一步&#xff1a;格式化硬盘 第二步&#xff1a;硬盘重新分区 固态硬盘分区 机械硬盘分区 完成效果展示 第三步&#xff1a;把ISO镜像文件写入固态硬盘 第四步&#xff1a;关机拔u盘 第五步&#xff1a;开机重装系统成功 前言 1.要重装系统&am…

Webpack提取页面公共资源

1. 利用html-webpack-externals-plugin 分离基础库 在做React开发时&#xff0c;经常需要引入react和react-dom基础库&#xff0c;这样在打包的时候速度就会比较慢&#xff0c;这种情况下我们可以将这些基础库忽略掉&#xff0c;将它们通过CDN的方式直接引入&#xff0c;而不打…

apache和IIS区别?内网本地服务器项目怎么让外网访问?

Apache和IIS是比较常用的搭建服务器的中间件&#xff0c;它们之间还是有一些区别差异的&#xff0c;下面就详细说说 Apache和IIS有哪些区别&#xff0c;以及如何利用快解析实现内网主机应用让外网访问。 1.安全性 首先说说apache和IIS最基本的区别。Apache运行的操作系统通常为…

Python数学建模问题总结(3)数据可视化Cookbook指南·下

概括总结&#xff1a;五、样式&#xff1a;优化图表、数据可视1.形状&#xff1a;形状的精确程度&#xff1b;2.颜色&#xff1a;区分类别、表示数量、突出特定数据、表示含义&#xff1b;3.线&#xff1a;点划线或不同的不透明度&#xff1b;4.文字排版&#xff1a;应用于图表…

IOC/DI配置管理第三方bean及注解开发。

目录 一、IOC/DI 配置管理第三方bean 1、配置第三方bean 2、加载properties 文件 3、核心容器 二、注解开发 1、注解开发定义bean 2、纯注解开发模式 3、注解开发bean作用范围与生命周期管理 4、注解开发依赖注入 三、IOC/DI注解开发管理第三方bean 1、注解开发管…