自动采集编写(神策Android全埋点插件的含义及含义插件介绍)
优采云 发布时间: 2021-12-10 08:00自动采集编写(神策Android全埋点插件的含义及含义插件介绍)
一、前言
在上一篇文章《神测Android全插件介绍》中,我们了解到神测Android插件其实就是一个自定义的Gradle插件。Gradle 是一个专注于灵活性和性能的开源自动化构建工具,插件的作用是打包模块化、可重用的构建逻辑。您可以通过插件实现特定的逻辑,并打包分享给他人。例如,神测Android全埋点插件在编译时利用该插件处理特定功能,从而实现控件点击和Fragment页面浏览的全埋点采集。
在本文中,我们将首先介绍Gradle 的基础知识,然后举例说明如何实现自定义Gradle 插件。这里需要注意的是,文章使用./gradlew来执行Gradle命令,如果你是Windows用户,需要将它改成gradlew.bat。
二、Gradle 基础知识
Gradle 有两个重要的概念:Project 和 Task。本节将介绍它们各自的功能以及它们之间的关系。
2.1 项目介绍
项目是与 Gradle 交互中最重要的 API。我们可以通过Android Studio的项目结构来理解Project的含义,如图2-1所示:
图2-1 Android Studio 项目*敏*感*词*
图2-1是编写过程中用到的一个项目(名为BlogDemo),收录两个Module,app和plugin。在这里,“Project”和“Module”在构建过程中都会被Gradle抽象为Project对象。他们的主要关系是:
1、Android Studio 结构中的项目相当于一个父项目,一个项目中的所有模块都是父项目的子项目;
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源代码的任务、编译Android资源的任务、编译JNI的任务、混淆任务、生成Apk文件的任务、运行App的任务等。你还可以在Build中看到实际运行了哪些任务Android Studio的输出,如图2-2所示:
图 2-2 Android Studio Build 输出日志
从图中右侧,我们可以看到Task由两部分组成:任务所在的Module名称和任务名称。在运行Task时,也需要通过这种方式指定一个Task。
此外,您可以自定义您自己的任务。让我们创建最简单的任务:
// add to build.gradle
task hello {
println 'Hello World!'
}
这段代码的意思是创建一个名为“hello”的Task。如果想单独执行Task,可以在Android Studio的Terminal中输入“./gradlew hello”,执行后就可以看到控制台输出了。你好世界!”。
三、Gradle 插件构建3.1 插件介绍
Plugin和Task其实和它们的功能没有太大区别。它们都封装了一些业务逻辑。Plugin适用于打包需要复用的编译逻辑的场景(即模块化部分编译逻辑)。您可以自定义 Gradle 插件,实现必要的逻辑并将其发布到远程仓库或作为本地 JAR 包共享。这样,以后想再次使用或者分享给别人的时候,可以直接引用远程仓库包或者引用本地JAR包。
最常见的 Plugin 应该是 Android 官方提供的 Android Gradle Plugin。可以在项目主模块的build.gradle文件第一行看到:“apply plugin:'com.android.application'”,就是Android Gradle Plugin。“com.android.application”指的是插件id,插件的作用是帮你生成一个可运行的APK文件。
该插件还可以读取 build.gradle 文件中写入的配置。在main Module的build.gradle文件中会有一个名为“android”的block,里面定义了一些属性,比如App支持的最低系统版本,App的版本号等,大家可以比较一下“ android" android 块在这里作为数据类或基类,定义的属性类似于类成员变量。Android Gradle Plugin 可以在运行时获取“android”块实例化的对象,然后根据对象的属性值运行不同的编译逻辑。
3.2 为独立项目构建 Gradle 插件
Gradle插件的实现方式有3种,分别是Build脚本、buildSrc项目和Standalone项目:
1、Build 脚本会直接在 build.gradle 文件中写入逻辑,Plugin 只对当前 build.gradle 文件可见;
2、buildSrc项目就是在rootProjectDir/buildSrc/src/main/java(最后一个路径文件夹也可以是groovy或者kotlin,看你用什么语言实现自定义插件)目录下写逻辑,Plugin仅对当前项目有效;
3、独立项目就是把逻辑写在一个单独的项目中,可以直接编译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”的文件,然后添加package、class语句;
3、资源都需要手动创建,文件夹名需要仔细拼写;
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.plugin
class 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.properties
implementation-class=com.sensorsdata.plugin.MyPlugin
3.2.3 发布插件
插件全部内容写完后,在终端执行
./gradlew uploadArchive
您可以发布插件。在上一节写的插件的build.gradle文件中,发布到maven仓库的相关配置是提前配置好的,所以我们这里执行这个命令后,项目根目录下就会出现repo文件夹,文件夹收录打包的 JAR 文件。
3.2.4 使用插件
使用插件有两个主要步骤: