前言
热修复,是目前一个比较热门的技术。它可以在app已上线的情况下,无需重新发布安装包,就可以修复bug。为线上修复紧急bug,提供了一个很便捷也比较人性化的途径。
传统开发与热修复开发的比较
传统开发:
从流程来看,传统的开发流程存在很多弊端:
重新发布版本代价太大;
用户下载安装成本太高;
BUG修复不及时,用户体验太差。
热修复开发:
而热修复的开发流程显得更加灵活,优势很多:
无需重新发版,实时高效热修复;
用户无感知修复,无需下载新的应用,代价小;
修复成功率高,把损失降到最低。
主流方案
目前比较主流、著名的有阿里巴巴的AndFix、Dexposed,腾讯QQ空间的超级补丁技术和微信的Tinker。
而今天,介绍的是微信的Tinker方案。
具体操作
添加依赖库
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.7.7')
//tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.7.7')
生成apk
① 创建项目,添加application
@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);
}
}
android:name=".SimpleTinkerInApplication"
如果字显示为红色,请build一下就可以了。
② 添加patch
public class MainActivity extends AppCompatActivity {
private Context context;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化界面
*/
private void initView() {
context = this;
textView = (TextView) findViewById(R.id.main_tv);
}
/**
* 点击按钮 加载patch
*
* @param view
*/
public void loadPatch(View view) {
TinkerInstaller.onReceiveUpgradePatch(context,
Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed.apk");
}
}
这里需要权限,需要在清单文件中添加:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/main_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="bug修复前!" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="loadPatch"
android:text="加载patch" />
</LinearLayout>
③ 打包生成旧的apk(即有bug的apk)
这里,我使用的是源码中提供的签名文件。源码见:tinker-patch-cli
注意:我们可以直接使用官方提供的签名文件和密钥签名,密钥其实在tinker_config.xml文件中有写,是:testres。
④ 复制旧apk的mapping文件
路径:app->build->outputs->mapping->release->mapping.txt
复制此文件到和proguard-rules.pro同级的目录下。
注意:此步骤是混淆代码的情况下。如果没有混淆代码,忽略此步骤。
⑤ 修复bug,生成新apk
注意:如果之前是混淆代码的情况,这个步骤需要在proguard-rules.pro中添加:
-applymapping mapping.txt
如果没有混淆代码,忽略此注意。只需要按照步骤生成新的apk就可以了。
生成Patch
如何生成patch呢?
patch是比较前后两个app的不同而生成的。
tinker提供了patch生成的工具,打成一个jar就可以使用,并且提供了命令行相关的参数以及文件。
我们可以看到,源码中为我们提供了生成patch需要的资源。
路径为:
生成patch的命令为:
java -jar tinker-patch-cli-1.7.7.jar -old old.apk -new new.apk -config tinker_config.xml -out output
我们用命令行,cd到资源文件目录下,直接使用此命令就好了。
注意:
A:jar文件请到我的优快云中下载。链接为:tinker-patch-cli-1.7.7.jar
B:output文件夹是要输出patch时候使用到的,请提前创建
C:tinker_config.xml中的
<loader value="tinker.sample.android.SampleApplication"/>
替换成自己的application。
输入此命令后,成功的话,会出现类似这种的界面展示:
此时,output文件夹下,会生成:
测试热修复效果
① 在手机中安装旧apk;
② 将patch_signed.apk pull到手机中;
③ 点击app界面中的『加载patch按钮』app会重启,再次点开app时,发现TextView变成了『bug修复后~』。验证成功!!!
注意:
过程中,因为手机版本不同。权限可能没有给到,会报错:
size 3324 verifyPatchMetaSignature fail
案例分享