介绍
产品上线后发现了一个小bug,急需修复,以热修复补丁方式动态修复紧急bug,不再需要重新发布App,不再需要用户重新下载,覆盖安装。目前开源了许多的热修复框架:如Jasonross 的Nuwa,美团的Robust,阿里的Andfix,腾讯的Tinker 等等。
本文使用腾讯的Tinker :
引入:
Add tinker-gradle-plugin as a dependency in your main build.gradle
in the root of your project:
buildscript {
dependencies {
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')
}
}
Then you need to "apply" the plugin and add dependencies by adding the following lines to your app/build.gradle
.
dependencies {
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.9.1')
//tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.9.1')
}
...
...
apply plugin: 'com.tencent.tinker.patch'
API主要就是初始化和loadPacth。
正常情况下,我们会考虑在Application的onCreate中去初始化,不过tinker推荐下面的写法:
@DefaultLifeCycle(application = ".SimpleTinkerInApplication",
flags = ShareConstants.TINKER_ENABLE_ALL,
loadVerifyFlag = false)
public class SimpleTinkerInApplicationLike extends ApplicationLike {
public SimpleTinkerInApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
}
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
}
@Override
public void onCreate() {
super.onCreate();
TinkerInstaller.install(this);
}
}
ApplicationLike通过名字你可能会猜,并非是Application的子类,而是一个类似Application的类。
tinker建议编写一个ApplicationLike的子类,你可以当成Application去使用,注意顶部的注解:@DefaultLifeCycle
,其application属性,会在编译期生成一个SimpleTinkerInApplication
类。
所以,虽然我们这么写了,但是实际上Application会在编译期生成,所以AndroidManifest.xml
中是这样的:
<application
android:name=".SimpleTinkerInApplication"
.../>
编写如果报红,可以build下。
这样其实也能猜出来,这个注解背后有个Annotation Processor在做处理,如果你没了解过,可以看下:
通过该文会对一个编译时注解的运行流程和基本API有一定的掌握,文中也会对tinker该部分的源码做解析。
上述,就完成了tinker的初始化,那么调用loadPatch的时机,我们直接在Activity中添加一个Button设置:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void loadPatch(View view) {
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(),
Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed.apk");
}
}
我们会将patch文件直接push到sdcard根目录;
所以一定要注意:添加SDCard权限,如果你是6.x以上的系统,自己添加上授权代码,或者手动在设置页面打开SDCard读写权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- 1
除以以外,有个特殊的地方就是tinker需要在AndroidManifest.xml
中指定TINKER_ID。
<application>
<meta-data
android:name="TINKER_ID"
android:value="tinker_id_6235657" />
//...
</application>
patch生成详见:https://blog.csdn.net/chaoyu168/article/details/79718196
本文参考:https://blog.csdn.net/lmj623565791/article/details/54882693
BUG参考:https://blog.csdn.net/hao_m582/article/details/78694439