多渠道打包工具美团walle解析
Walle
知识点
- ApplicationInfo.sourceDir 获取已安装应用对应的安装文件apk
- 系统安装apk时是如何做签名校验的
- 基于ZIP文件格式和APK Signing Block存储格式而构建,基于文件的二进制流进行处理
- ZIP文件的格式是
[local file header + file data + data descriptor]{1,n} + central directory + end of central directory record [文件头+文件数据+数据描述符]{此处可重复n次}+核心目录+目录结束标识 当压缩包中有多个文件时,就会有多个[文件头+文件数据+数据描述符]
首先我们找到
end of central directory record的起始位置,从末尾开始找,因为comment的长度不固定,还得遍历一下,得到comnentLength-
得到comnentLength后,根据eocd的格式构成,可以知道 central directory 的size(offset16 4位表示)。得到了centralDirStartOffset
-
这样我们可以准确定位到 APK Signing Block 的存储区域
-
分析 APK Signing Block 的格式
- 该块包含ID值对,这种方式使得APK更容易找到该块,APK的v2签名存储在ID为0x7109871a的键值对中。
- ZIP文件的格式是
GradlePlugin 插件分析学习呀呀呀呀呀
知识点
-
已经可以用kotlin编写gradle文件了,语法清晰,可读性好,支持语法高亮,代码补全,代码跳转 https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/
-
DSL(Domain Specific Language’) 领域专用语言。DSL的简洁性往往是一种思维上的简洁性,使我们不用费太多的气力就能看懂代码所对应的业务含义。Groovy是一种开源的脚本语言,在Java基础上进行了扩展,支持闭包、动态类型、元编程等特性。
- 构建模型
- 是个有向无环图
- 三个构建阶段
- 初始化阶段,解析 settings.build 哪些project会参与构建
- 配置阶段,构建task的有向无环图,执行属于配置阶段的代码,解析 build.gradle
- 执行阶段,按序执行task
//setting.gradle println 'This is executed during the initialization phase.' // settings.gradle 中的代码在初始化阶段执行 //build.gradle println 'This is executed during the configuration phase.' // 在配置阶段执行 // 普通的自定义 Task task testBoth { doFirst { println 'This is executed first during the execution phase.' // doFirst 中的代码在执行阶段执行 } doLast { println 'This is executed last during the execution phase.' // doLast 中的代码在执行阶段执行 } println 'This is executed during the configuration phase as well.' // 非 doFirst 或者 doLast 中的代码,在配置阶段执行 } -
一个
build.gradle对应一个Project对象,在gradle文件中可通过project属性访问该对象。 rootProject属性代表根Project对象,即项目根目录下的build.gradle文件。 - Project是由一系列的task组成,你可以自定义task,也可以继承已有的task,如Copy Delete
task customTask(){ doLast{ print '自定义任务' } } - 如何访问task。通过
TaskContainer对象,在gradle文件中通过 tasks 属性访问该对象afterEvaluate { def aTask = tasks.getByName('assembleDebug') println "aTask name is ${aTask.name}" aTask.dependsOn(customTask) // 这样执行 assembleDebug 前都会执行customTask } -
在build.gradle中调用属性,或调用Project.property(java.lang.String)方法时,会按顺序从以下范围查找:
- Project自身定义的属性
- Project的Extra属性
- 插件添加的Extension属性
- 插件添加的Convension属性
- Project中Task的名字
- 从父Project继承的属性,一直递归到RootProject
在build.gradle中调用方法时,会按顺序从以下范围查找:
- Project自身定义的方法
- build.gradle脚本定义的方法
- 插件添加类型为Action或Closure的Extension
- 插件添加的Convension方法
- Project中Task的名字都会创建一个对应方法
- 从父Project继承的方法,一直递归到RootProject
- Project中为Closure类型的属性可以作为方法调用
- Task代表构建过程中的一个原子操作,每个Task属于一个Project。每个Task都有一个名字。所属Project名+Task名可组成唯一的完整名 每个Task包含一个Action序列,并在Task执行时按先后顺序执行。通过Task的doFirst/doLast方法可以往Action序列的头部/末尾添加Action,支持Action或闭包(闭包会被转换成Action对象)
每个Task可以依赖其他Task,执行Task时会先执行其依赖的Task,通过dependsOn可设置依赖。每个Task还可以设置在其他Task之前、之后执行,一般可通过mustRunAfter设置。 例如下面的配置,执行A时一定会先执行B;执行A不一定会执行C;当A、C都要执行时一定先执行C。
taskA.dependsOn(taskB) taskA.mustRunAfter(taskC)
* Task的创建
在build.gradle中创建Task,最常见写法如下。task(xxx)是Project提供的API,最终调用了TaskContainer的create方法。可接收参数包括:
Task名称(必选)
Map<String, ?>类型配置(可选)
闭包配置(可选)
* 还可以用类实现Task,创建Task时指定type为这个class即可,并且还可以传参数 [gradle基础](https://www.paincker.com/gradle-develop-basics)
- PluginAware主要定义了插件相关API,
GradleSettingsProject等接口均继承了PluginAware接口。
apply plugin:’java’ 其中 plugin:’java’ 是一个map类型 apply plguin:’com.android.application’ 编译android的插件,独立的复杂的大插件,研究的也是这个。
apply from:’xxx/my_script.gradle’ 注意在 my_script 中定义的属性和方法,build.gradle无法访问,因为每个gradle文件都编译成单独的Groovy Script,这些属性只是Script类的成员。
如果在不同脚本之间传递数据,可以利用Gradle/Setting/Project对象的ext属性实现。
- 简易插件开发 下面的示例代码实现了HelloPlugin的简易插件,代码可直接写在build.gradle中。
插件在apply(Project)方法里,给Project创建了一个名为hello的Extension和一个名为welcome的Task;Task执行时读取Extension并打印字符串。
在build.gradle执行到apply plugin: HelloPlugin时,HelloPlugin.apply(Project)方法被执行,从而Project有了hello的Extension,于是后面可以调用hello {}对插件进行配置。
class HelloExtension {
Boolean enable = true
String text = ''
}
class HelloPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.extensions.create('hello', HelloExtension)
project.task('welcome') {
doLast {
HelloExtension ext = project.extensions.hello;
println ext.enable ? "Hello ${ext.text}!" : 'HelloPlugin is disabled.'
}
}
}
}
apply plugin: HelloPlugin
hello {
enable = true
text = 'Gradle'
}
在命令行中执行结果如下。
$ ./gradlew welcome
:welcome
Hello Gradle!
BUILD SUCCESSFUL
Total time: 0.917 secs
blog comments powered by Disqus