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

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

作者: SMSM | 来源:发表于2018-02-08 20:45 被阅读21次

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

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/racxtftx.html