@Awille
2018-12-15T09:29:09.000000Z
字数 3871
阅读 120
Android Gradle Plugin
Gradle是一个构建工具,它是用来帮助我们构建app的,构建包括编译、打包等过程。
在解析 Gradle 的编译过程之前我们需要理解在 Gradle 中非常重要的两个对象。Project和Task。
每个项目的编译至少有一个 Project,一个 build.gradle就代表一个project,每个project里面包含了多个task,task 里面又包含很多action,action是一个代码块,里面包含了需要被执行的代码。
整个project我们的gradle文件结构
MyProject
|-----module1
|-----build.gradle //模块1 gradle
|-----module2
|-----build.gradle //模块2 gradle
|-----build.gradle //整个项目的gradle,其配置会被应用到整个项目当中
|-----setting.gradle //定义哪些module会被加到编译过程
Gradle脚本的执行分为三个过程:
初始化
分析有哪些module将要被构建,为每个module创建对应的 project实例。这个时候settings.gradle文件会被解析。
配置:处理所有的模块的 build 脚本,处理依赖,属性等。这个时候每个模块的build.gradle文件会被解析并配置,这个时候会构建整个task的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表)。
执行:根据task链表来执行某一个特定的task,这个task所依赖的其他task都将会被提前执行。
整个project的编译过程是由一个个task执行实现的。
整个app基本 编译打是由 application插件实现的
apply plugin: 'com.android.application'
首先查看其apply方法:
@Override
public void apply(@NonNull Project project) {
super.apply(project);
}
此处调用了父类的apply方法:
@Override
public void apply(@NonNull Project project) {
// We run by default in headless mode, so the JVM doesn't steal focus.
//省略初始化与错误检查
threadRecorder = ThreadRecorder.get();//初始化线程信息记录者
ProcessProfileWriter.getProject(project.getPath())
.setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION)
.setAndroidPlugin(getAnalyticsPluginType())
.setPluginGeneration(GradleBuildProject.PluginGeneration.FIRST)
.setOptions(AnalyticsUtil.toProto(projectOptions));
BuildableArtifactImpl.Companion.disableResolution();
if (!projectOptions.get(BooleanOption.ENABLE_NEW_DSL_AND_API)) {//检查是否是最新的api
TaskInputHelper.enableBypass();
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
project.getPath(),
null,
this::configureProject);
//在配置工程阶段,主要做的是创建一些后续阶段会用到的对象,其中最重要的当属androidBuilder
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
project.getPath(),
null,
this::configureExtension);
//配置扩展阶段,其实做的事和之前阶段一样,也是创建对象,在创建的这些对象中,
//大家会看到个单词——variant,这就是常说的构建变体。
threadRecorder.record(
ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
project.getPath(),
null,
this::createTasks);
//plugin的task创建
} else {
//省略旧版实现
}
}
查看调用了三次的record方法的实现:
回头看basePlugin里的3个回调方法configureProject、configureExtension、
createTasks,方法里传的type已经暴露了他们的作用:
1、BASE_PLUGIN_PROJECT_CONFIGURE:plugin的基础设置、初始化工作
2、BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION:EXTENSION的初始化工作
3、BASE_PLUGIN_PROJECT_TASKS_CREATION:plugin的task创建
最终找到创建项目task的方法:
@Override
public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {
//............
// Add a task to publish the applicationId.
createApplicationIdWriterTask(variantScope);
// Add a task to process the manifest(s)
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_MANIFEST_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createMergeApkManifestsTask(variantScope));
// Add a task to create the res values
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_GENERATE_RES_VALUES_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> createGenerateResValuesTask(variantScope));
// Add a task to merge the resource folders
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_RESOURCES_TASK,
project.getPath(),
variantScope.getFullVariantName(),
(Recorder.VoidBlock) () -> createMergeResourcesTask(variantScope, true));
recorder.record(
ExecutionType.APP_TASK_MANAGER_CREATE_PROCESS_RES_TASK,
project.getPath(),
variantScope.getFullVariantName(),
() -> {
// Add a task to process the Android Resources and generate source files
createApkProcessResTask(variantScope);
// Add a task to process the java resources
createProcessJavaResTask(variantScope);
});
//..............
}
assemble依赖的task大致包括:
1、applicationIdWriter:发布
2、ApplicationIdmergeApkManifests:处理清单文件
3、generateResValues:生成ResValues
4、compileJavaWithJavac:编译java文件
5、mergeAssets收集所有assetspackage:打包生成apk
6、processResource:处理资源文件
实现iconCover,其中processResource这个task就是我们的关注点,可以在这个task上加一些action来实现我们的功能。
BaseVariant 不同的版本变体
applicationVariant 整个应用的变体集合
GraphicsEnviroment
具体见技术分享的ppt(这个内容是我做的技术分享)
ppt地址:
自定义插件
密码: HA5T