接入说明
instantRun 方式仅支持原生 AAR 接入方式。
InstantRun 新特性
满足一定条件下,支持不重启修复;
支持 so 修复 ;
支持资源修复;
生成补丁的时候不需要类白名单。
技术原理
Java 修复
通过对 JavaMethod 进行预插桩,实现动态的逻辑替换。
构建 Patch 需要修改源码,因此无法修改代码的三方库不能实现修复。
so 修复
原始 so 未加载可立即生效。
资源修复
通过固定资源 id 而进行新增和修改。
前置条件
采用原生 AAR 方式接入,需要先 将mPaaS 添加到您的项目中。
不要混用 dexPatch 热修复方式和 instantRun 热修复方式。
新旧 APK 包中的 so 文件数量和名字需要保持一致,否则无法打出热修复补丁且不支持修复。
必须使用 10.2.3-20 及以上基线版本,如你是 10.1.68 基线版本按照文档进行 mPaaS 10.2.3 升级指南。
添加 SDK
原生 AAR 方式
参考 管理组件依赖,通过 组件管理(AAR)在工程中安装 热修复(Hotfix)组件。
初始化热修复
原生 AAR 接入
如果需要使用热修复功能,您还需要完成以下两步操作。
需要将
Application
对象重新继承为QuinoxlessApplicationLike
,并注意将该类防混淆。此处以 MyApplication 为例。@Keep public class MyApplication extends QuinoxlessApplicationLike implements Application.ActivityLifecycleCallbacks { private static final String TAG = "MyApplication"; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); Log.i(TAG, "attacheBaseContext"); } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); registerActivityLifecycleCallbacks(this); } @Override public void onMPaaSFrameworkInitFinished() { MPHotpatch.init(); LoggerFactory.getTraceLogger().info(TAG, getProcessName()); } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log.i(TAG, "onActivityCreated"); } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }
在 AndroidManifest.xml 文件中将
Application
对象指向 mPaaS 提供的Application
对象。将刚刚生成的 MyApplication 类添加到 key 为mpaas.quinoxless.extern.application
的meta-data
中。示例如下:<application android:name="com.alipay.mobile.framework.quinoxless.QuinoxlessApplication" > <meta-data android:name="mpaas.quinoxless.extern.application" android:value="com.mpaas.demo.MyApplication" /> </application>
其中
com.mpaas.demo.MyApplication
是您自定义的 Application 代理类,继承QuinoxlessApplicationLike
。引入 Apache HTTP 客户端。
在使用热修复功能的时候,需要调用到 Apache HTTP 客户端相关的功能。只需在
AndroidManifest.xml
加入如下代码。更多信息,请参见使用 Apache HTTP 客户端。<uses-library android:name="org.apache.http.legacy" android:required="false"/>
instantRun 插桩配置和依赖
instantRun Maven
maven {
url "https://mvn.cloud.alipay.com/nexus/content/repositories/open/"
}
instantRun 插桩依赖
工程 app 主 module 下 build.gradle 文件中添加如下依赖:
apply plugin: 'com.android.application'
apply plugin: 'com.alipay.instantrun'
工程根目录下 build.gradle 文件中添加如下插件依赖:
dependencies {
classpath "com.mpaas.android.patch:patch-gradle-plugin:1.0.7"
}
instantRun 插桩配置
创建 instantrun 文件夹
在主工程的 app 目录下创建 instantrun 文件夹,放入生成 patch.jar 需要使用的 mapping.txt
文件。
instantrun 文件夹中文件的说明及来源按以下方式操作放入:
以下文件必须每次发布版本前进行保留,当需要修复时需将上个版本保留好的替换到 instantrun 文件夹中。
在有 Bug 的项目工程中执行命令行 ./gradlew clean assembleRelease
生成以下文件:
instantrun/InstantRunMapping.txt.gz(构建后生成的 InstantRunMapping_release.txt.gz 或 InstantRunMapping_debug.txt.gz,产物在 ./build/outputs/instantrun/ 如有,则改名后放入)
instantrun/mapping.txt(原工程构建打 Release 包时的 mapping.txt,产物在 ./build/outputs/mapping/[debug|release]/mapping.txt)
instantrun/methodsMap.instantrun(原 Bundle 级别接入插桩生成的 methodsMap.instantrun,产物在./build/outputs/instantrun/methodsMap.instantrun 如有则放入)
添加 instantrun.xml 配置文件
在主工程的 app 目录下添加 instantrun.xml
配置文件,注意配置中的相关内容,请仔细斟酌每个选项:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<switch>
<!--true代表打开InstantRun,请注意即使这个值为true,InstantRun也默认只在Release模式下开启-->
<!--false代表关闭InstantRun,无论是Debug还是Release模式都不会运行InstantRun-->
<turnOnInstantRun>true</turnOnInstantRun>
<!--是否开启手动模式,手动模式会去寻找配置项patchPackageName包名下的所有类,自动的处理混淆,然后把patchPackageName包名下的所有类制作成补丁-->
<!--这个开关只是把配置项patchPackageName包名下的所有类制作成补丁,适用于特殊情况,一般不会遇到-->
<manual>false</manual>
<!--是否强制插入代码,InstantRun默认在debug模式下是关闭的,开启这个选项为true会在debug下插入代码-->
<!--但是当配置项turnOnInstantRun是false时,这个配置项不会生效-->
<forceInsert>false</forceInsert>
<!--配置Patch函数匹配规则,默认为函数签名,可修改为函数序号,存储在methodsMap.instantrun中-->
<!--其中signature模式切面占用空间较大,而id模式切面占用空间会更小一些,更适合在乎安装包大小的App使用-->
<!--<methodMatchMode>signature</methodMatchMode>-->
<methodMatchMode>id</methodMatchMode>
<!--是否捕获补丁中所有异常,建议上线的时候这个开关的值为true,测试的时候为false-->
<catchReflectException>false</catchReflectException>
<!--是否在补丁加上log,建议上线的时候这个开关的值为false,测试的时候为true-->
<patchLog>true</patchLog>
<!--项目是否支持progaurd-->
<proguard>true</proguard>
</switch>
<!--需要HotPatch的包名或者类名,这些包名下的所有类都会被插入代码-->
<!--这个配置项是各个Bundle需要自行配置,就是你们Bundle里面你们自己代码的包名,
这些包名下的类会被InstantRun插入代码,没有被InstantRun插入代码的类InstantRun是无法修复的-->
<acceptPackageName name="acceptPackage">
<name>com.</name>
<name>android.</name>
<name>org.</name>
</acceptPackageName>
<!--不需要InstantRun插入代码的包名,InstantRun库不需要插入代码,如下的配置项请保留,还可以根据各个APP的情况执行添加-->
<exceptPackageName name="exceptPackage">
<name>com.alipay.euler</name>
<name>com.alipay.dexpatch</name>
<name>com.alipay.instantrun</name>
<name>ohos.</name>
<name>com.alipay.mobile.quinox.LauncherApplication</name>
</exceptPackageName>
<!--不需要InstantRun插桩的函数访问类型和对应包名列表,按需插桩,可降低接入包大小-->
<methodExceptConfig name="methodExceptConfig">
<privateMethodPackage>
<name>com.instantrun.demo</name>
</privateMethodPackage>
<packageMethodPackage>
<name>com.instantrun.demo</name>
</packageMethodPackage>
<protectedMethodPackage>
<name>com.instantrun.demo</name>
</protectedMethodPackage>
<publicMethodPackage>
<name>com.instantrun.demo</name>
</publicMethodPackage>
<syntheticMethodPackage>
<name>com.instantrun.demo</name>
</syntheticMethodPackage>
</methodExceptConfig>
<!--补丁的包名,请保证唯一性,填写apk包名即可-->
<patchPackageName name="patchPackage">
<name>com.instantrun.demo</name>
</patchPackageName>
</resources>
修改 Bug 代码
Java 函数修复方式
首先接入上述的构建依赖与配置;
需要在改动的方法上面添加以下注解:
@com.alipay.instantrun.patch.annotaion.Modify
//修改方法 @com.alipay.instantrun.patch.annotaion.Modify protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } //或者是被修改的方法里面调用 com.alipay.instantrun.patch.InstantRunModify.modify()方法 protected void onCreate(Bundle savedInstanceState) { com.alipay.instantrun.patch.InstantRunModify.modify() super.onCreate(savedInstanceState); }
对于 Lambda 表达式,需要在修改的方法里面调用:
com.alipay.instantrun.patch.InstantRunModify.modify()
。//修改方法 @com.alipay.instantrun.patch.annotaion.Modify protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } //或者是被修改的方法里面调用com.alipay.instantrun.patch.InstantRunModify.modify()方法 protected void onCreate(Bundle savedInstanceState) { com.alipay.instantrun.patch.InstantRunModify.modify() super.onCreate(savedInstanceState); }
新增的类、方法使用
@com.alipay.instantrun.patch.annotaion.Add
注解。//增加方法 @com.alipay.instantrun.patch.annotaion.Add public String getString() { return "InstantRun"; } //增加类 @com.alipay.instantrun.patch.annotaion.Add public class NewAddCLass { public static String get() { return "instantRun"; } }
so 修复方式
修改相关 C/C++ 代码或 so 即可,然后打包新的 so 替换工程中有问题的 so 库。
资源修复方式
支持任何资源文件的修复和添加,但不支持 so 库资源的添加。
资源 ID 固定配置
下载 生成资源文件的工具 Jar 包 获取需要修复的 apk 包资源 id,执行以下命令行:
java -jar ~/path/stableResourcesId.jar ~/path/old.apk ~/path/values
生成的产物在目标目录下。
将上面命令行生成的
public.xml
、ids.xml
两个文件产物放入到新工程(修复好的工程)的~/res/values
目录中。将
public.txt
文件放入到新工程(修复好的工程)的根目录中。然后在 app moudle 的
build.gradle
文件中的 android 节点下进行如下配置:aaptOptions { File publicTxtFile = project.rootProject.file( 'public.txt') if (publicTxtFile.exists()) { additionalParameters "--stable-ids", "${project.rootProject.file ('public.txt').absolutePath}" } }
进行补丁打包配置
在 Android Studio 的 mPaaS 插件中,进入 基础工具 > 热修复 > 生成补丁(instant run)页面。
说明
如果是修改或者新增 res/layout
下的 xml
布局文件,则需在 Java 代码层进行 Java patch 加入修改的注解以及获取对应的资源 id,再进行加载。
使用 instantRun
生成 patch.jar 产物
patch.jar 是生成热修复补丁包的关键,包含了需要修复的内容,在最新修复的工程输出即可,在终端按如下命令行执行生成:
./gradlew clean mpGeneratePatch
生成的产物在工程的 ./build/outputs/instantrun/patch.jar
目录下。
生成热修复 instantRun 补丁
在 Android Studio 的 mPaaS 插件工程中进行补丁生成,如下所示:
单击 基础工具 > 热修复 > 生成补丁(instant run)。
进入生成补丁页面,填写相关修复信息项。
输入项含义说明
New bundle:选择最新修复好的 apk 包路径。
Old bundle:选择有 bug 的 apk 包路径(线上版本)。
PatchJarPath dir:工程中接入 instantRun 执行命令行
./gradlew clean mpGeneratePatch
打出的patch.jar
路径。Patch out dir:存放补丁包产物的路径。
重要New bundle 和 Old bundle 中的 apk 包不能存放到 C 盘的 User 目录下和中文目录下。
单击 Next 进入填写签名信息页面。
确保填写的签名信息准确,否则会导致生成失败。
填写完成后单击 Create 即可生成补丁。
使用热修复
将补丁包发布到控制台,具体参考文档 使用热修复。
查看日志
热更新请求日志
过滤 Tag 中包含 DynamicRelease 的日志;
InstantRun 执行日志
过滤 Tag 中包含 IR. 的日志;
Patch 执行日志
在打 Patch 前,在构建配置 instantrun.xml 中打开 patchLog 选项。 过滤 Tag 中包含 IR.PatchCode 的日志。包含 invoke method is 的日志行,表示执行了对应函数的 Patch。