Tinker接入
- 项目的build.gradle文件中添加插件依赖
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.5')
- 主moudle下的build.gradle文件中添加配置
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch'
- 配置Tinker插件中需要的参数
//这里只配置一些必须的参数
tinkerPatch {
//有bug的apk
oldApk = "${bakPath}/app-debug-1227-22-24-45.apk"
buildConfig {
//旧版apk唯一标示,避免使用MD5,比较耗时
//这个id也会在补丁包中存在,和apk做对比。
tinkerId = "1.0"
}
dex {
//这里指定的类不参与补丁包构建,并且必须在主dex包中。
loader = ["com.tencent.tinker.loader.*","com.zzc.androidtrain.app.BaseApplication"]
}
lib {
//参与补丁构建的so包资源
pattern ["lib/armeabi/*.so","lib/arm64-v8a/*.so","lib/armeabi-v7a/*.so","lib/mips/*.so","lib/mips64/*.so","lib/x86/*.so","lib/x86_64/*.so"]
}
res {
//参与补丁构建的应用资源,一定要包含apk中所有的资源
pattern ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
//资源变更超过100kb,使用bsdiff算法来减少文件尺寸
largeModSize = 100
}
//生成补丁包时(assets/package_meta.txt)添加的包信息
//除了添加默认的tinker_id,tinker_id_value等,还可以在这里定义自己需要的信息
//通过TinkerLoadResult.getPackageConfigByName方法获取
packageConfig {
configField("patchVersion", "1.0")
}
//使用的压缩工具
sevenZip {
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
//path = "/usr/local/bin/7za"
}
}
修改Application类
Tinker把原来所有在Application中的操作委托到了一个代理类中,继承自ApplicationLike,默认实现为DefaultApplicationLike。所以我们也需将Application中的初始化操作移动DefaultApplicationLike的子类中去。public class BaseApplicationDelegate extends DefaultApplicationLike { @Override public void onBaseContextAttached(Context base) { super.onBaseContextAttached(base); //初始化Tinker //注:此处base.getApplicationContext()为null TinkerManager.installTinker(this); } @Override public void onCreate() { //初始化其他组件 } }
那么,我们自己原来的Application怎么办呢?两种方式
第一:由继承Application改为继承TinkerApplication,在构造方法中,传入上面提到的代理类
public class BaseApplication extends TinkerApplication {
public BaseApplication() {
super(ShareConstants.TINKER_ENABLE_ALL, "com.zzc.androidtrain.app.BaseApplicationDelegate", "com.tencent.tinker.loader.TinkerLoader", false);
}
}
第二:使用注解。在上述代理上添加注解
“`
@DefaultLifeCycle(application=”tinker.sample.android.app.SampleApplication”,
flags = ShareConstants.TINKER_ENABLE_ALL,
loadVerifyFlag = false)
public class BaseApplicationDelegate extends DefaultApplicationLike前提是需在主模块build.gradle文件中添加注解依赖
provided(‘com.tencent.tinker:tinker-android-anno:1.7.6’)
“`- 加载补丁文件
在从服务器下载补丁文件完成后,加载。
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk");
关键问题
- 多个dex会产生多个patch dex
- 需要重启生效
- dex全量更新
- 不能新增四大组件及AndroidManifest.xml文件变更
- 在单独进程合并补丁包
- 在主进程加载补丁包
- 部分三星手机不支持
- 受google应用分发机制,海外版本不能做动态更新
- 采用Application代理模式,使类Application初始化类也可做热修复,更重要的是解决Android N系统上的混合编译对热修复带来的影响。
- 加载补丁失败,有最多重试3次的保护机制
- 提供多进程文件操作的文件锁(FileLock)
原理分析
补丁包构建
- 使用nio walkFileTree方法遍历压缩包文件
- dex文件结构https://source.android.com/devices/tech/dalvik/dex-format.html
- 构建流程图