sdk-editor-plugin

Introduction: This is a gradle plugin for android to edit class in SDK.
More: Author   ReportBugs   
Tags:

  • 支持 Android Gradle Plugin 4.2.x
  • 原有@ReplaceClass("包标识"),中的"包标识"改为把依赖库格式[group:name:version]中的[name:version]作为标识,如:原依赖[androidx.core:core:1.3.0@aar],则取[core:1.3.0]作为标识,请不要添加[version]后面的@aar
  • 发布仓库由 jcenter 迁移到 jitpack

简介

  • sdk-editor 是一个在 APP 编译期修改类的轻量 Gradle 插件,插件利用 Android Plugin 官方提供的 Transform API 干预 APK Build 流程,实现对特定类的替换修改。无其他不安全 Hook 操作,100%可靠。

  • 如果 APP 中某个依赖的 SDK 没有源码、无人迭代,并且发现 Bug 或者需要扩展功能,那么 sdk-editor 就是你的菜!

    特点

  • 使用简单方便,不需要任何字节码知识;

  • 编译期替换,不影响 App 性能,不增加 Apk 体积(仅添加一个用于标记的注解类 ReplaceClass);

    适用场景

  • 修复 SDK 中存在的 Bug;

  • 暴露出 SDK 某些未提供的接口;

  • 扩展 SDK 功能;

  • 其他需要修改 SDK 已有类的需求;

    基本用法

    1. 在根项目(最外层)的 build.gradle 文件中添加插件依赖:

    buildscript {
      repositories {
      ...
      maven { url 'https://jitpack.io' }
      }
      dependencies {
          classpath 'com.github.iwhys:sdk-editor-plugin:1.1.7'
      }
    }
    

    2. 在项目主模块(app module)的 build.gradle 文件应用插件:

    apply plugin: 'sdk-editor'
    

    3. 找到三方 SDK 中需要修改的类文件(以下称为 Bug 类),在 app module 中新建与 Bug 类同包名同类名的新类(以下称为 Fix 类),同时拷贝 Bug 类的内容到 Fix 类,给 Fix 类添加类注解@ReplaceClass,在注解的值中标记该类所在 SDK(jar/aar)的标识(依赖格式[group:name:version]只取[name:version]作为标识),最后在 Fix 类中实现要修改的内容即可。

下面以 demo module 中替换 core:1.3.0 包中的 BuildCompat 类为例进行说明,我们需要 BuildCompat 类中的 isAtLeastR 方法,在其中添加一条 Toast 语句,修改流程如下:

1)在 demo 工程的 main/java 下新建 androidx.core.os.BuildCompat 类;

2)拷贝原 SDK 中 BuildCompat 类的内容,并修改新建的 BuildCompat 类;

/** 原依赖[androidx.core:core:1.3.0] 取[core:1.3.0]作为标识 **/
@ReplaceClass("core:1.3.0")
public class BuildCompat {
    public static boolean isAtLeastR() {
        Toast.makeText(MyAppKt.getAppContext(), "You successfully added a Toast to \"BuildCompat#isAtLeastQ()\"", Toast.LENGTH_LONG).show();
        return VERSION.CODENAME.length() == 1
                        && VERSION.CODENAME.charAt(0) >= 'R'
                        && VERSION.CODENAME.charAt(0) <= 'Z';
    }
}

3)编译并运行 demo,点击按钮弹出一个 Toast,即表明 core:1.3.0 包中的 BuildCompat 类被成功的修改;

高级用法

如果有多个项目用到了同一个需要修改的 SDK,为了在多个项目中共享修复后的代码,我们可以把修复代码封装成一个单独 jar/aar 包。下面以 demo 模块中 libs 引用的三方 SDK DuappsAd-HW-v1.1.1.6-release.aar 为例,我们需要修改 SDK 中的 com.duapps.ad.DuNativeAd 类,在其中添加广告请求监听器,具体流程如下:

1)在任意项目中新建一个 module(如工程中的 library_fix);

2)在 module 的 build.gradle 文件中添加对需要修复的 SDK(如:DuappsAd-HW-v1.1.1.6-release.aar)以及插件注解包(com.iwhys.classeditor:domain:1.1.0)的依赖;

3)在 module 的 main/java 目录下新建包 com/duapps/ad,并在 com/duapps/ad 中新建 DuNativeAd 类,同时拷贝原 SDK 中 DuNativeAd 类的内容

4)在新建的 DuNativeAd 类中添加注解@ReplaceClass("DuappsAd-HW-v1.1.1.6-release");

5)在新建的 DuNativeAd 类中添加需要新增的广告监听器逻辑;

6)在终端(Terminal)中执行命令:gradlew library_fix:build,即可在该 module 的 build/output 目录中看到生成的 aar 文件;

7)重命名 aar 文件(或者其中的 jar 文件)为:du_hack,拷贝该文件到主 module(app module)的 libs 文件夹,并添加对该文件的依赖;

8)在主 module(app module)的 build.gradle 中指定用于 SDK 修复的 jar/aar 包信息即可,格式如下:

sdkEditor {
    // 这里是一个数组,有多个用于修复的包,需要用","分隔开
    extraJarNames = ['hack_du']
}

9)此时主 module(app module)便可以在编译的时候使用 jar/aar(hack_du)中的 Fix 类来替换原 SDK 中的 Bug 类;

10)插件默认使用单线程处理任务,可通过配置 parallel 开启多线程并发来提高处理速度;

sdkEditor {
    // 默认值为 false,即单线程处理任务
    parallel = true
}

常见问题

1. 新建与 Bug 类同包名的 Fix 类时,编译器提示"Package 'xxx.xxx.xxx' clashes with class of same name"

这种情况是因为包路径中的包和类重名了,我们可以通过把 java 类转换为 kotlin 类来修复这个问题。

注意:此时需要添加 kotlin 相关的支持,且因为 kotlin 编译器在把类编译为 class 的时候,默认会把文件名改为:原文件名+kt,因此在 kotlin 版的 Fix 类中添加文件命名注解 @file:JvmName("Bug 类的名称")

2. 在新建的 Fix 类中,存在部分形如"a.b.c"的类无法正确的导入,或者导入之后与当前类的成员重名

这种情况我们可以把类改为 kotlin 版,并利用 kotlin 提供的 import xxx as yyy 功能,对导入的有问题的类进行重命名。个人感觉通过导入重命名方式能够解决 99%的这种问题,剩下的 1%可以通过反射来实现。

3. 新建的 Fix 类时,如果其所在包的名字同级已经存在一个同名的类(如已存在类 com.a.a,Fix 类路径 com.a.a.Fix,则 IDE 提示"Redeclare a")

我们可以通过"高级用法"的笨办法,新建 module 把已存在类 com.a.a 和 Fix 类 com.a.a.Fix 分别放在不同的 module 来实现。

4. Fix 过程正常,但是 APK 运行到 Fix 类发生 Crash,提示 Fix 类中缺少 xxx 方法

通常我们会使用 IDE 来浏览依赖的 SDK 文件,并在 IDE 中把 Bug 类的源码拷贝到 Fix 类中,但有些情况下 IDE 反编译的 class 代码并不完整,建议使用 jeb 反编译 SDK 中的 Bug 类。

项目简析

sdk-editor 结构及原理简析

特别感谢

javassist

协议

The Apache Software License, Version 2.0

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools