上一篇热修复学习(2):TinkerSDK集成比较方便,但是补丁存在三方平台且更新受三方限制,这一篇的思路是在启动app时获取是否需要更新,然后下载并且加载补丁。
1.在项目的build.gradle中添加依赖
buildscript {
dependencies {
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')
}
}
2.在app的gradle文件中添加配置
注意Tinker需要使用到MulitDex 所以要填MulitDex的依赖
//Gradle版本小于2.3的这么写
dependencies {
compile "com.android.support:multidex:1.0.1" //可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.9.1') //tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.9.1') }
//Gradle版本大等于2.3的这么写
dependencies {
implementation "com.android.support:multidex:1.0.1" //tinker的核心库
implementation("com.tencent.tinker:tinker-android-lib:1.9.1") { changing = true } //可选,用于生成application类
annotationProcessor("com.tencent.tinker:tinker-android-anno:1.9.1") { changing = true }
compileOnly("com.tencent.tinker:tinker-android-anno:1.9.1") { changing = true } }
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch
defaultConfig {
...
multiDexEnabled true
}
3.配置Tinker的设置
配置巨多请参考 build.gradle官方demo的gradle文件,这里只说一下会用到属性
ext {
// 是否使用Tinker(当你的项目处于开发调试阶段时,可以改为false)
tinkerEnabled = true
// 基础包文件路径(名字这里写死为old-app.apk。用于比较新旧app以生成补丁包,不管是debug还是release编译)
tinkerOldApkPath = "${bakPath}/old-app.apk"
// 基础包的mapping.txt文件路径(用于辅助混淆补丁包的生成,一般在生成release版app时会使用到混淆,所以这个mapping.txt文件一般只是用于release安装包补丁的生成)
tinkerApplyMappingPath = "${bakPath}/old-app-mapping.txt"
// 基础包的R.txt文件路径(如果你的安装包中资源文件有改动,则需要使用该R.txt文件来辅助生成补丁包)
tinkerApplyResourcePath = "${bakPath}/old-app-R.txt"
4.Tinker的自定义功能
Tinker官方文档:可选的自定义类
可以直接复制到项目中,一般只修改bug可能用不到这些,这里只做了解
可以从Tinker的官方demo下拷贝
简单说明下,这几个文件的作用:
SampleUncaughtExceptionHandler:Tinker的全局异常捕获器。
MyLogImp:Tinker的日志输出实现类。
SampleLoadReporter:加载补丁时的一些回调。
SamplePatchListener:过滤Tinker收到的补丁包的修复、升级请求。
SamplePatchReporter:修复或者升级补丁时的一些回调。
SampleTinkerReport:修复结果(成功、冲突、失败等)。
SampleResultService::patch补丁合成进程将合成结果返回给主进程的类。
TinkerManager:Tinker管理器(安装、初始化Tinker)。
TinkerUtils:拓展补丁条件判定、锁屏或后台时应用重启功能的工具类。
5.Application的修改
修改是为了动态的修改Application类
代码如下
@SuppressWarnings("unused")
/// application类名。只能用字符串,这个MyApplication文件是不存在的,但可以在AndroidManifest.xml的application标签上使用(name)
@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",
flags = ShareConstants.TINKER_ENABLE_ALL,
loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {
private static final String TAG = "Tinker.SampleApplicationLike";
public SampleApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,
long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
/**
* install multiDex before install tinker
* so we don't need to put the tinker lib classes in the main dex
*
* @param base
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
//you must install multiDex whatever tinker is installed!
MultiDex.install(base);
SampleApplicationContext.application = getApplication();
SampleApplicationContext.context = getApplication();
TinkerManager.setTinkerApplicationLike(this);
TinkerManager.initFastCrashProtect();
//should set before tinker is installed
TinkerManager.setUpgradeRetryEnable(true);
//optional set logIml, or you can use default debug log
TinkerInstaller.setLogIml(new MyLogImp());
//installTinker after load multiDex
//or you can put com.tencent.tinker.** to main dex
TinkerManager.installTinker(this);
Tinker tinker = Tinker.with(getApplication());
// 将之前自定义的Application中onCreate()方法所执行的操作搬到这里..
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {
getApplication().registerActivityLifecycleCallbacks(callback);
}
}
图片.png
6.常用的Api
请求打补丁
TinkerInstaller.onReceiveUpgradePatch(context, 补丁包的本地路径);
卸载补丁
Tinker.with(getApplicationContext()).cleanPatch();// 卸载所有的补丁
Tinker.with(getApplicationContext()).cleanPatchByVersion(版本号)// 卸载指定版本的补丁
Hack方式修复so
TinkerLoadLibrary.installNavitveLibraryABI(this, abi);
7.测试
打补丁方式与上一篇类似,测试的时候可以用下面的命令将补丁导入手机中
adb pushpatch_signed_7zip.apk文件路径 /storage/sdcard0/(手机存放的路径)
再用上面的加载补丁api即可
网友评论