自动采集编写( AndroidStudio的Gradle插件含义及构建逻辑的含义和关系)
优采云 发布时间: 2022-01-19 17:11自动采集编写(
AndroidStudio的Gradle插件含义及构建逻辑的含义和关系)
一、前言
在上一篇文章 文章 中,我们了解到 Sensors Android 插件实际上是一个自定义的 Gradle 插件。Gradle 是一款专注于灵活性和性能的开源自动化构建工具,插件用于打包模块化、可重用的构建逻辑。具体逻辑可以通过插件实现,打包分享给他人使用。例如,Sensors Android全埋插件通过该插件在编译时处理特定功能,从而实现控制点击和Fragment页面浏览的全埋点采集。
在本文中,我们将首先介绍 Gradle 的基础知识,然后举例说明如何实现自定义 Gradle 插件。这里需要注意的是,本文使用 ./gradlew 来执行 Gradle 命令。如果是Windows用户,需要改成gradlew.bat。
二、Gradle 基础
Gradle 有两个重要的概念:项目和任务。本节将介绍它们各自的作用以及它们之间的关系。
2.1 项目介绍
Project 是与 Gradle 交互的最重要的 API。我们可以通过Android Studio的项目结构来理解Project的含义,如图2-1所示:
图2-1 Android Studio项目*敏*感*词*
图2-1是编写过程中用到的一个项目(名为BlogDemo),包括两个Modules,app和plugin。无论是“项目”还是“模块”,在构建的时候都会被 Gradle 抽象成一个 Project 对象。他们的主要关系是:
1、Android Studio结构中的一个项目相当于一个父项目,一个项目中的所有Module都是父项目的子项目;
2、每个Project都会对应一个build.gradle配置文件,所以在使用Android Studio创建项目的时候,根目录下有一个build.gradle文件,每个Module里面都有一个build.gradle文件目录。分级文件;
3、Gradle 使用 settings.gradle 文件构建多个项目。项目之间的关系也可以从图2-1中看出。
父Project对象可以获取所有子Project对象,这样就可以在父Project对应的build.gradle文件中进行一些统一的配置,例如:管理依赖的Maven中心库:
...allprojects { repositories { google() jcenter() }}...
2.2 任务介绍
Project 在构建过程中执行一系列任务。Task的中文翻译是“任务”。它的功能其实就是抽象出一系列有意义的任务。用 Gradle 的官方说法是:每个任务都执行一些基本的工作。例如:当您点击 Android Studio 的 Run 按钮时,Android Studio 将编译并运行该项目。其实这个过程是通过执行一系列Task来完成的。可能包括:编译Java源码的Task,编译Android资源的Task,编译JNI的Task,混淆的Task,生成Apk文件的Task,运行App的Task等Android Studio的构建输出,如图2-2所示:
图 2-2 Android Studio Build 输出日志
从图右侧,我们可以看到Task由两部分组成:Task所在的Module名称和Task的名称。运行Task时,也需要通过这种方式指定Task。
另外,您可以自定义和实现自己的Task,让我们创建一个最简单的Task:
// add to build.gradletask hello { println 'Hello World!'}
这段代码的意思是创建一个名为“hello”的Task。如果要单独执行Task,可以在Android Studio的Terminal中输入“./gradlew hello”,执行后可以看到控制台输出“Hello World!”。
三、Gradle 插件搭建3.1 插件简介
Plugin 和 Task 在功能上并没有太大区别。它们都封装了一些业务逻辑。Plugin适用于打包需要复用的编译逻辑(即模块化部分编译逻辑)。您可以自定义 Gradle 插件,实现必要的逻辑并将其发布到远程存储库或作为本地 JAR 包共享。这样,当你想再次使用或者分享给别人的时候,可以直接引用远程仓库中的包或者引用本地的JAR包。
最常见的Plugin应该是Android官方提供的Android Gradle Plugin。可以在项目主Module的build.gradle文件的第一行看到:"apply plugin:
'com.android.application'",Android Gradle 插件。
“com.android.application”是指插件id,插件的作用是帮助你生成一个可运行的APK文件。
插件还可以读取 build.gradle 文件中写入的配置。在主Module的build.gradle文件中会有一个名为“android”的block,block中定义了一些属性,比如:App支持的最低系统版本,App的版本号等等在。你可以把这里的“android”块想象成一个数据类或者基类,定义的属性作为类的成员变量。Android Gradle Plugin可以在运行时获取“android”块实例化的对象,然后根据对象的属性值运行不同的编译逻辑。
3.2 用于构建独立项目的 Gradle 插件
Gradle 插件的实现方式有 3 种,分别是 Build script、buildSrc 项目和 Standalone 项目:
1、构建脚本会直接在 build.gradle 文件中写入逻辑,Plugin 只对当前的 build.gradle 文件可见;
2、buildSrc项目会在rootProjectDir/buildSrc/src/main/java(最后路径文件夹也可以是groovy或者kotlin,看你用什么语言实现自定义插件)目录下写逻辑,Plugin只有效对于当前项目;
3、Standalone project是把逻辑写在一个独立的项目里,可以直接编译发布JAR包到远程仓库或者本地。
基于写这篇文章的目的,这里我们主要讲解Standalone项目,也就是独立项目的Gradle插件。
3.2.1 目录结构分析
一个独立项目的 Gradle 插件的一般结构如图 3-1 所示:
图3-1 Gradle插件项目目录*敏*感*词*
主文件夹分为groovy文件夹和resources文件夹:
其中,resources文件夹下是固定格式的META-INF/gradle-plugins/XXXX.properties,XXXX代表以后使用插件时需要指定的插件id。
目前Android Studio对Gradle插件开发的支持还不够好。IDE 可以执行的许多任务需要手动完成,例如:
1、Android Studio不能直接创建Gradle插件的Module,只能先创建Java Library类型的Module,然后删除多余的文件夹;
2、新类默认为新Java类,新文件名后缀为“.java”。如果要新建一个Groovy语法类,需要手动新建一个后缀为“.groovy”的文件,然后添加包、类声明;
整个3、resources需要手动创建,文件夹名需要拼写;
4、删除Module的build.gradle的全部内容,添加Gradle插件和Gradle插件开发所需的依赖。
3.2.2 编写插件
在编写插件的代码之前,我们需要对 build.gradle 进行一些更改,如下所示:
apply plugin: 'groovy'apply plugin: 'maven'
dependencies { implementation gradleApi() implementation localGroovy()}
uploadArchives{ repositories.mavenDeployer { //本地仓库路径,以放到项目根目录下的 repo 的文件夹为例 repository(url: uri('../repo')) //groupId ,自行定义 pom.groupId = 'com.sensorsdata.myplugin' //artifactId pom.artifactId = 'MyPlugin' //插件版本号 pom.version = '1.0.0' }}
主要分为三个部分:
1、apply plugin:应用'groovy'插件是因为我们的项目是使用Groovy语言开发的,以后发布插件时会用到'maven'插件;
2、dependencies:声明依赖;
3、uploadArchive:这里有一些maven相关的配置,包括发布仓库的位置、groupId、artifactId、版本号。为方便调试,位置选择在项目根目录下的repo文件夹中。
做好以上准备后,就可以开始编写源代码了。Gradle插件要求入口类需要实现org.gradle.api.Plugin接口,然后在实现方法apply中实现自己的逻辑:
package com.sensorsdata.pluginclass MyPlugin implements Plugin{ @Override void apply(Project project) { println 'Hello,World!' }}
在这里的例子中,apply方法是我们整个Gradle插件的入口方法,类似于各种语言中的main方法。apply方法的输入参数类型Project在第二节已经说明,这里不再赘述。由于Plugin类和Project类有很多同名的类,所以在导入的时候一定要选择org.gradle.api包下的类。
最后还需要做一个准备工作:Gradle插件不会自动查找入口类,而是需要开发者在resources/META-INF/gradle-plugins/XXXX.properties中写入入口类的类名。内容格式为“implementation-class=入口类的完全限定名”,此处示例工程的配置如下:
// com.sensorsdata.plugin.propertiesimplementation-class=com.sensorsdata.plugin.MyPlugin
3.2.3 发布插件
为插件编写完所有内容后,在终端中执行
./gradlew uploadArchive
可以发布插件。上一节写插件的build.gradle文件中提前配置了发布到maven仓库相关的配置,所以我们这里执行命令后,项目根目录下会出现repo文件夹,文件夹收录打包的 JAR 文件。
3.2.4 使用插件
使用插件有两个主要步骤: