从项目中的build.gradle,罗列的知识点。
什么是闭包?
相当于C中的函数指针,或者Java中的引用。
-----from Groovy----
mHandler.post{
getPresenter().requestAdsData()
}
setOnClickListener(mRecyclerView) { v ->
v.setVisibility(View.GONE)
}
----from Java----
mHandler.post(()->{getPresenter().requestAdsData()};);
setOnClickListener(mRecyclerView,v -> {v.setVisibility(View.GONE);});
对比有什么不同,Groovy中,入参只有一个并且是个闭包时,可省略圆角括号;入参最后一个参数为闭包时,该闭包可以单独用花括号包裹并放在圆括号外面。这是语法上的不同。
如何新建Task?以及执行时机?
task clean(type: Delete) {
delete rootProject.buildDir
}
创建task的过程
1 Task task(Map<String, ?> args, String name, Closure configureClosure); 创建指定类型的Task,也就是org.gradle.api.tasks.Delete
2 调用configureClosure闭包,执行delete函数,入参是rootProject.buildDir。到此cleantask实例创建、初始化成功。
3 执行./gradlew clean。执行clean的action。比如被@TaskAction标注的函数。
练习,猜一下下面日志的输出顺序
task demo2 {
println 'demo2'
doLast {
println 'demo2 doLast'
}
doFirst {
println 'demo2 doFirst'
}
}
修改build.gradle 后点击sync now刷新,以下为输出log顺序
---->demo2
$ ./gradlew demo2
---->demo2
--->demo2 doLast
--->demo2 doFirst
Gradle工作流程
Gradle工作流程层级关系是这样的gradle -- rootProject -- subProject -- task -- action
Gradle工作包含三个阶段:
首先Initiliazation phase是初始化阶段。对我们前面的multi-project build而言,就是执行settings.gradle,得知有多少subProject。
Configration阶段的目标是解析每个project中的build.gradle,根据引入的plugin,生成每个task已经初始化了的taskGraph。可hook,比如,关闭某些task、插入自定义task、自定义的action。
最后一个阶段执行指定的以某个接口为头结点的task依赖树,头结点是解析./gradlew xxx得到的。
生成的taskGraph长什么样子呢?调用./gradlew assembleDebug 后发生了什么
:app:assembleDebug
+--- :app:compileDebugSources
| +--- :app:compileDebugJavaWithJavac
| | +--- :app:generateDebugSources
| | | +--- :app:compileDebugAidl
| | | | \--- :app:prepareDebugDependencies
| | | | +--- :app:checkDebugManifest
| | | | | \--- :app:preDebugBuild
| | | | | \--- :app:preBuild
| | | | +--- :app:preDebugBuild *
\--- :app:packageDebug
+--- :app:compileDebugJavaWithJavac *
+--- :app:mergeDebugAssets
| +--- :app:generateDebugAssets
| | \--- :app:compileDebugShaders
| | \--- :app:mergeDebugShaders
| \--- :app:prepareDebugDependencies *
+--- :app:processDebugResources *
+--- :app:transformClassesWithDexForDebug
| +--- :app:transformClassesWithJarMergingForDebug
| | \--- :app:transformClassesWithJavassistForDebug
| | +--- :app:compileDebugJavaWithJavac *
| | +--- :app:prepareDebugDependencies *
| \--- :app:transformClassesWithMultidexlistForDebug
| \--- :app:transformClassesWithJarMergingForDebug *
+--- :app:transformNativeLibsWithMergeJniLibsForDebug
| +--- :app:compileDebugNdk *
| +--- :app:mergeDebugJniLibFolders
| | +--- :app:generateDebugAssets *
| | \--- :app:prepareDebugDependencies *
| +--- :app:prepareDebugDependencies *
| +--- :coredata:bundleRelease **
| \--- :rxmvpkit:bundleRelease *
+--- :app:transformResourcesWithMergeJavaResForDebug
| +--- :app:prepareDebugDependencies *
| +--- :app:processDebugJavaRes
\--- :app:validateSigningDebug
深度遍历后的结果是:
:app:preBuild SKIPPED
:app:preDebugBuild SKIPPED
:app:checkDebugManifest SKIPPED
:app:mergeDebugAssets SKIPPED
:app:prepareDebugDependencies SKIPPED
:app:compileDebugAidl SKIPPED
:app:compileDebugRenderscript SKIPPED
:app:generateDebugBuildConfig SKIPPED
:app:generateDebugResValues SKIPPED
:app:generateDebugResources SKIPPED
:app:mergeDebugResources SKIPPED
:app:processDebugManifest SKIPPED
:app:processDebugResources SKIPPED
:app:compileDebugJavaWithJavac SKIPPED
:app:transformClassesWithJavassistForDebug SKIPPED
:app:transformClassesWithJarMergingForDebug SKIPPED
:app:transformClassesWithMultidexlistForDebug SKIPPED
:app:transformClassesWithDexForDebug SKIPPED
:app:mergeDebugJniLibFolders SKIPPED
:app:transformNativeLibsWithMergeJniLibsForDebug SKIPPED
:app:processDebugJavaRes SKIPPED
:app:transformResourcesWithMergeJavaResForDebug SKIPPED
:app:validateSigningDebug SKIPPED
:app:packageDebug SKIPPED
:app:assembleDebug SKIPPED
开始搞事情——如何知道Android APK依赖的Jar包中哪些文件包含指定字符?
- 涉及DSL Groovy语法
- Android构建流程
- 如何自定义GradlePlugin、Task
- Class文件格式解析
思路:分三步
找到Apk依赖的所有的Jar包 和 Class文件 -----》 解压Jar解析Class内容 ----》 输出文件名。
解析Class
常量池 ------FragmentTransaction ft; 属性-------
18 Field #45, name&type #104
104 NameAndType #52, type #53
52 UTF8 "ft"
53 UTF8 "Landroid/support/v4/app/FragmentTransaction;"
45 Class #134
134 UTF8 "com/mrzhang/component/MainActivity"
MainActivity ft FragmentTransaction 参数类型因为有内部类,所以要指定是哪个类的属性
对应的smali
class的字节码
找到hook点,插入Task
Gradle打包流程转化为Dex之前,可插入Task,输入为当前apk依赖的所有jar和class。自定义一个Transform 或者在 app:compileDebugJavaWithJavac 后面
如何定义一个插件
插件开发过程图涉及概念点extension、task、plugin入口、maven管理
https://github.com/Tencent/tinker 例子
把每种技能比喻为一把刀,平时我们用的是菜刀,现在一块大骨头面前想吃牛骨髓,怎么办?不知道大家喜不喜欢吃?就需要一把砍刀。工作中你有多少把刀?
多了一把刀,多了一种解决问题的方式和思路,比如我们用的三方源码库实现方式的过程从 APO -> APT -> Gradle,不断迁移,也更强大,也是赋能量、更自由的过程。
网友评论