如何扫描Android APK依赖的Jar包中哪些文件包含指定字

2018-02-08  本文已影响21人  SMSM

从项目中的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包中哪些文件包含指定字符?

  1. 涉及DSL Groovy语法
  2. Android构建流程
  3. 如何自定义GradlePlugin、Task
  4. Class文件格式解析

思路:分三步
找到Apk依赖的所有的Jar包 和 Class文件 -----》 解压Jar解析Class内容 ----》 输出文件名。

解析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,不断迁移,也更强大,也是赋能量、更自由的过程。

上一篇下一篇

猜你喜欢

热点阅读