Android Gradle 插件自定义Plugin实现注意事项

目录
  • Android Gradle Plugin
    • Gradle 是什么?
    • Gradle 插件
    • 分类
    • 使用插件
  • 实现一个插件
  • 发布插件
  • 引用插件

Android Gradle Plugin

在 Android 项目中的 build.gradle 文件中,经常可以看见一些 plugin 声明:

plugins {
    id 'com.android.application'
	  id 'com.android.library'
}
// or
apply plugin: 'com.android.application'
apply plugin: 'com.android.library'

上面是两种引用 gradle 插件的常用代码,com.android.application 是用来构建 apk 的 gradle 插件;com.android.library 是用来构建 Android Library 的 gradle 插件。

Gradle 是什么?

Gradle 是自动化构建工具,多项目构建而设计的。通过 groovy 或 kotlin 来编写构建脚本。主要用来处理:

  • 自动处理包依赖关系
  • 自动处理部署问题

过去 Java 开发者常用 Maven 和 Ant 等工具进行封装布署的自动化,或是两者兼用,不过这两个包彼此有优缺点:

  • 如果频繁改变相依包版本,使用 Ant 相当麻烦,
  • 如果琐碎工作很多,Maven 功能不足
  • 而且两者都使用 XML 描述,相当不利于设计 if、switch 等判断式,即使写了可读性也不佳

而 Gradle 改良了过去 Maven、Ant 带给开发者的问题,至今也成为 Android Studio 内置的封装布署工具。

官方文档:What is Gradle?

Gradle 插件

Gradle 的核心是提供自动化处理流程。所有有用的特性,比如编译 Java 代码的能力,都是由插件添加的。

插件实际的作用有:

  • 拓展 Gradle Model (例如:添加可配置的新 DSL 元素)
  • 根据约定配置项目(例如:添加新的 Gradle Task 或配置一些合理的默认值)
  • 应用指定的配置(例如:添加一些仓库或执行标准)

好处:

通过应用插件,而不是向项目构建脚本添加逻辑,可以获得的好处有:

  • 提高复用能力,减少跨多个项目维护类似逻辑的开销:同一个插件可以应用到不同的项目。
  • 更好的模块化:通过插件的形式,可以使项目架构更加明确更容易理解。
  • 封装重要的逻辑,允许构建脚本尽可能具有声明性。

分类

Gradle 插件有两种类型,分为二进制插件和脚本插件。

二进制插件:

  • 二进制插件可以通过实现 org.gradle.api.Plugin 接口以编程方式编写,也可以使用 Gradle 的一种 DSL 语言以声明方式编写。
  • 二进制插件可以驻留在构建脚本中、项目层次结构中或外部插件 jar 包中。

脚本插件:

  • 脚本插件是额外的构建脚本,可以进一步配置构建并且通常实现一种声明性的方法来操作构建。它们通常在构建中使用,尽管它们也可以外部化并从远程位置访问。
  • 插件通常以脚本插件开始(因为它们易于编写),然后随着代码变得更有价值,它被迁移到可以在多个项目或组织之间轻松测试和共享的二进制插件。

使用插件

要使用插件中封装的构建逻辑,Gradle 需要执行两个步骤。 首先,解析插件,然后需要将插件应用到一个目标上,通常是一个 org.gradle.api.Project 对象。

  • 解析插件:解析插件的工作是找到包含给定插件的正确版本的 jar 并将其添加到脚本类路径中。一旦一个插件被解析,它的 API 就可以在构建脚本中使用。
  • 应用插件:应用插件意味着在要使用插件的项目上实际执行插件的Plugin.apply(T 。应用插件是幂等的。也就是说,您可以安全地多次应用任何插件而不会产生副作用。

本篇文章主要介绍如何实现一个二进制插件。

实现一个插件

最简单的构建 Gradle 插件的方式是 通过命令来构建:

gradle init // or ./gradlew init

执行命令:

  • 第一步,选择项目类型,4 是 Gradle 插件项目。
  • 第二步,选择实现芋圆,这里主要是 插件的代码语言,支持 Groovy、Java 和 Kotlin。
  • 第三步,选择 DSL 语言(构建脚本语言),支持 Groovy 和 Kotlin。
  • 第四步,输入项目名称和插件包名。

最后会显示构建结果。 构建完的项目结构是这样的:

这里有很多不需要的文件目录,包括用来测试和 Gradle 的一些相关内容,都可以删除(当然你也可以不处理),因为当我们把这个项目引入到一个 Android 项目中时,Android 项目提供了 Gradle 相关文件。

如图所示,ExamplePlugin 目录下 gradle 相关的文件,在 Android 的根目录中都存在。 其中构建插件相关的内容都在 build.gradle 文件中,首先是,插件项目引用的插件:

plugins {
    id 'java-gradle-plugin'
    id 'maven' // maven 仓库
    id 'groovy'	// groovy 支持
}

需要重点注意的是,使用一些第三方依赖如果下载不到,要检查引用的远程仓库是否在包含想要引用的依赖:

repositories {
    // Use JCenter for resolving dependencies.
    jcenter()
}

当我想引用 com.android.tools.build:gradle 依赖时,一直报错,原因是 jcenter 中不存在这个项目,需要添加 google()

然后是一些依赖:

dependencies {
    // ...
    testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
}

接下来是比较重要的插件定义:

gradlePlugin {
    // Define the plugin
    plugins {
        customName {
            id = 'com.example.plugin.customname'
            implementationClass = 'com.example.plugin.ComExamplePluginPlugin'
        }
    }
}

这里需要注意的是 customName 是你可以随意定义的字符串,这个字符串会在 Plugin.apply 方法中使用到。 Id 就是插件唯一标识,后续在其他项目中引用的时候,也是引用这个 id 。 implementationClass 的值指向一个实际的代码类,这个类实现了 org.gradle.api.Plugin 。 自动生成的 Plugin 实现类是这样的:

class ComExamplePluginPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Register a task
        project.tasks.register("customName") {
            doLast {
                println("Hello from plugin 'com.example.plugin.customname'")
            }
        }
    }
}

在这个 apply 方法中,使用之前我们定义的 customName 注册了一个 Task 。 实际上 Gradle 后续就是执行这个 Task ,来执行代码块中的代码的。

在很多之前的 Gradle 插件实现方案中,需要创建 resources/META-INF/gradle-plugin/xxx.properties ,而通过上面的方式,不需要在去创建这个文件了。 这样一个插件的定义基本上就完成了。

发布插件

我们已经定义好了一个 Gradle 插件,那么应该如何校验这个插件是否真的能够使用呢?为了解决这个问题,我们要把 Gradle 插件发布到远程仓库或者本地目录,然后供其他项目引用,以此来测试插件。 以本地发布为例,在插件项目的根目录下的 build.gradle 文件中添加:

plugins {
	  // ...
    id 'maven-publish' // 用来发布插件
}
publishing {
    repositories {
        maven {
            // $rootDir 表示你项目的根目录
			  // 这里配置发布到的本地目录
            url = "$rootDir/repo"
        }
    }
    publications {
        publish(MavenPublication) {
            // 插件的组ID,建议设置为插件的包名
            groupId = 'com.example.plugin.customname'
            // 插件的名字,后续在引用时会用到
            artifactId = 'customName'
            version = '0.0.1'
            // 组件类型
            from components.java
        }
    }
}

如果发布到本地,运行 Gradle 命令:

./gradlew publishPublishPublicationToMavenLocal

则会发布到本地目录 /Users/XXX/.m2/repository/ 中。

./gradlew publishPublishPublicationToMavenRepository

会发布到你在 build.gradle 中,指定的目录 "$rootDir/repo" 中。

引用插件

在 Android 项目中引用的第一步是在根目录的 build.gradle中添加 maven 仓库,这样 Gradle 才能从特定的本地目录中找到我们的 jar 包:

repositories {
    jcenter()
    google()
    maven {
        url = "$rootDir/repo"
    }
}

第二步,在根目录的 build.gradle 中添加依赖:

dependencies {
    classpath "com.example.plugin.customname:customName:0.0.1"
}

这个就是我们在发布插件时,指定的 groupId 、artifactId 和 version,规则是:

classpath "$groupId:$artifactId:$version"

然后,在需要引用的 module 下的 build.gradle 文件中应用插件:

plugins {
    id 'com.example.plugin.customname'
}

这里的 id 是我们在定义插件时在 gradlePlugin 代码块中指定的。 这样我们就成功的通过 jar 包的形式引用到了插件。 这里以我另一个项目为例,我在 gradlePlugin 中指定的代码块自定义名称为 transfrom :

gradlePlugin {
    plugins {
        transform {
			 // ...
        }
    }
}

引用成功后会在 Gradle Task 中多一个同名的任务:

对应的 Groovy 中实现 apply 方法:

@Override
void apply(Project project) {
    project.tasks.register("transform") {
        doLast {
            println("Hello from plugin 'com.chunyu.transform.plugin'")
        }
    }
}

执行该任务,会看到 log 面板中有对应的输出:

> Task :app:transform
Hello from plugin 'com.chunyu.transform.plugin'

成功的验证了,在 apply 中 print 代码正确的执行了。

到此这篇关于Android Gradle 插件自定义Plugin实现注意事项的文章就介绍到这了,更多相关Android Gradle 插件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android Studio 中Gradle配置sonarqube插件(推荐)

    目录 一,使用公共Maven仓库: 二,使用私有Maven仓库: Sonarqube作为一个很实用的静态代码分析工具,在很多项目中都使用.Android自然也不例外.这里就分享下使用Android Studio时如何在Gradle里配置Sonarqube. 以下分别就使用公共maven仓库和私有maven仓库两种情况来简单说明下: 一,使用公共Maven仓库: 这个比较简单. 打开gradle sonarqube插件官方网址:https://plugins.gradle.org/plugin/o

  • Android开发gradle拉取依赖的加速配置

    目录 前言 情况1 : 情况2: 前言 镜像配置都是常规操作,必要时也可以上代理. 自己搭的nexus本质也是一种镜像,可以代理maven中央仓库. 各个仓库的测速,可以使用这个脚本: 通过测速,调整仓库的顺序 apply from: 'https://raw.githubusercontent.com/hss01248/flipperUtil/master/deps/depsLastestChecker.gradle' 情况1 : 每次点击sync project with gradle fi

  • Android Gradle同步优化详解

    目录 动态修改gradle配置 hook agp ProjectsServices 方法签名检查是否存在support包 年初开始我们就开始了关于Gradle Sync阶段的优化.之前和大家都简单的介绍过工程相关的背景情况了,我们大概有400+的Module,然后一次的同步时间就非常的慢,我们迫切的需要对这个问题进行优化.大部分工作都是和团队内的同学一起完成的,我也只出了一点点力而已. 这次写文章真的很倒霉,之前忘了保存导致要重新开始写了.如果不是白嫖了掘金的端午礼盒,拿人手短啊,我已经打算鸽了

  • Android开发之Gradle 进阶Tasks深入了解

    目录 前言 定义Task register与create的区别 查找Task 配置Task 将参数传递给Task构造函数 Task添加依赖 Task排序 Task添加说明 跳过Task 使用onlyIf 使用 StopExecutionException 禁用与启用Task Task超时 Task支持增量编译 Task的输入输出 自定义task类型 声明输入输出的好处 推断task依赖关系 输入和输出验证 并行task 增量编译原理解析 一些高端操作 将@OutputDirectory链接到@I

  • Android项目中gradle的执行流程

    目录 gradle文件执行流程 自定义gradle文件的导入方法 gradle中定义的变量如何被java代码使用 gradle文件执行流程 做过Android开发的同学都知道 ,Android项目中存在三个gradle文件,那你是否知道他们的执行流程呢?请看下面这张图: 为了验证结论 的正确性,我们采用输出字符串的验证方式: 输出结果如下: 自定义gradle文件的导入方法 上面所阐述的三个 gradle 文件是由系统来管理的,那我们能创建gradle文件吗?答案是肯定的. 那我们创建的 gra

  • Androd Gradle模块依赖替换使用技巧

    目录 背景 解决 步骤1: 步骤2: 步骤3: 背景 我们在多模块项目开发过程中,会遇到这样的场景,工程里依赖了一个自己的或者其他同事的 aar 模块,有时候为了开发调试方便,经常会把 aar 改为本地源码依赖,开发完毕并提交的时候,会再修改回 aar 依赖,这样就会很不方便,开发流程图示如下: 解决 一开始我们通过在 app 的 build.gradle 里的 dependency 判断如果是需要本地依赖的 aar,就替换为 implementation project 依赖,伪代码如下: d

  • Android Gradle 插件自定义Plugin实现注意事项

    目录 Android Gradle Plugin Gradle 是什么? Gradle 插件 分类 使用插件 实现一个插件 发布插件 引用插件 Android Gradle Plugin 在 Android 项目中的 build.gradle 文件中,经常可以看见一些 plugin 声明: plugins { id 'com.android.application' id 'com.android.library' } // or apply plugin: 'com.android.appli

  • 详解Android Gradle插件3.0挖坑日记

    为了提升编译速度,这几天用上了 AS 3.0 和 Gradle 3.0 插件,不得不说不论是 AS 3.0,还是 Gradle 3.0 都变化非常大,具体的更新日志参考下官网,其中 Gradle 3.0的配置和可能遇到的问题可以说是非常详细了.Gradle 4.1-all 官方下载速度很慢,我直接放出来下载地址和相关官方文档地址吧. Gradle 4.1 Android Studio Gradle 配置属性 下面来列决下我遇到的坑和解决方法: 配置属性的改动 Gradle 3.0 和之前有一点很

  • Android gradle插件打印时间戳的方法详解

    Android中时间戳的详细解释: (1).定义: 时间戳就是根据当前系统时间生成的一组随机数字. (2).作用: 作为对数据唯一性的一种判断依据.避免了重复修改数据所带来的错误! (3).应用: (1).在银行account表中建立时间戳字段timestamp,设定为文本类型varchar. (2).当银行A读取account表中的存款字段时,同时也读取时间戳字段,比如123456. (3).当银行A修改完存款数值后,进行存盘操作时,将先前读取的时间戳123456与当时表中的时间戳进行一次对比

  • Android自定义Gradle插件的详细过程

    一.Gradle 我们知道在我们现在使用Android Stduio开发Android项目的时候,Android Studio是基于Gradle来帮助我们构建,管理项目的. Gradle:Gradle是一个项目构建工具,用来帮助我们管理项目的依赖.打包.发布.部署等工作. Gradle是通过如build.gradle这种gradle脚本来进行项目构建的,所以我们对项目的构建配置都是可以写在gradle构建脚本中. gradle构建脚本使用的是Groovy语言,Groovy语言也是一种jvm语言,

  • Android Studio3.0升级后使用注意事项及解决方法

    Gradle plugin最高版本4.* 老的项目在使用新版本时,可能会出现gradle plugin冲突的问题 Error:Failed to open zip file. Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network)

  • 为Android Studio编写自定义Gradle插件的教程

    Google已经建议Android开发全部转向Android Studio开发,Android Studio 是使用gradle编译.打包的,那么问题来了,gradle可是有一堆东西...,为了彻底了解gradle,今天就来学习下如何写自己的gradle插件(当然插件源码是使用groovy写的),先看如下代码目录: 如上图所示,plugin目录是插件源码目录,sample是用来测试插件的. 1.在目录plugin/src/main/groovy/com/micky/gradle/下新建插件类My

  • 详解如何使用Android Studio开发Gradle插件

    缘由 首先说明一下为什么会有这篇文章.前段时间,插件化以及热修复的技术很热,Nuwa热修复的工具NuwaGradle,携程动态加载技术DynamicAPK,还有希望做最轻巧的插件化框架的Small.这三个App有一个共同的地方就是大量的使用了Gradle这个强大的构建工具,除了携程的框架外,另外两个都发布了独立的Gradle插件提供自动化构建插件,或者生成热修复的补丁.所以学习一下Gradle插件的编写还是一件十分有意义的事. 插件类型 Gradle的插件一般有这么几种: 一种是直接在项目中的g

  • Android Studio调试Gradle插件详情

    前言: 使用ASM在编译期修改字节码来完成各种功能(统计方法耗时.全埋点统计...),就需要开发Gradle插件.开发插件中遇到问题排查使用日志输出效率太低了,能断点调试的话就更好了.其实已经有很多文章写了调试插件的方法,但是自己照着他们的步骤下来还是遇到一些问题,把这些问题记录下来方便大家少走弯路. Android Studio版本是3.5.2,Gradle版本是3.5.1 1.点击[Run]->[Edit Configurations...]: 2.然后点击左上角的[+],选择[Remote

  • 详解MyBatis自定义Plugin插件

    作用 官方说明: MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用. 什么意思呢?就是你可以对执行某些方法之前进行拦截,做自己的一些操作,如: 1.记录所有执行的SQL(通过对 MyBatis org.apache.ibatis.executor.statement.StatementHandler 中的prepare 方法进行拦截) 2.修改SQL(org.apache.ibatis.executor.Executor中query方法进行拦截)等. 但拦截的方法调用有限制,My

  • Android Studio Gradle插件版本与Gradle版本之间的对应关系

    1.gradle插件版本配置位置: project对应的build.gradle文件中 buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' } } 2.gradle版本配置位置: gradle-wrapper.properties 中 distributionUrl=https\://services.gradle.org/distribu

随机推荐