手把手教你集成热修复Tinker。

时光怂恿深爱的人放手 提交于 2019-12-03 11:30:29

热更新: 就是在应用无需重新安装情况下实现更新,从而实现动态修复功能。

在热更新之前,如果线上的应用出现bug, 是需要用户重新下载然后安装,这样的操作对用户来说肯定是不能接受的,什么软件,时不时就重新下载安装,用户体验极差, 热更新出现之后,这样的问题就可以得到解决,在用户无感知的情况下就可以把bug修复。

目前比较火的热修复的分为阿里系、腾讯系、 其他大厂。

  1. 阿里系 : DeXposed 、 andfix 从底层二进制入手 (c语言)。
  2. 腾讯系 : tinker 、Qzone 从类加载入手 。
  3. 美团: Robust 从类加载入手 。

下面给出几个大厂的框架区别

在这里插入图片描述

在集成热更新之前,比较过几个框架,最终还是选择Tinker。 下面就介绍集成Tinker步骤。 跑通tinker中的demo

源码 : https://github.com/Tencent/tinker

1: 在工程目录下的build.gradle中,添加tinker-patch-gradle-plugin的依赖

classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')

在这里插入图片描述

2: 然后在app的gradle文件app/build.gradle, 需要添加tinker的库依赖以及apply tinker的gradle插件。

implementation('com.tencent.tinker:tinker-android-lib:1.9.1')
implementation("com.tencent.tinker:tinker-android-loader:1.9.1") { changing = true }
annotationProcessor("com.tencent.tinker:tinker-android-anno:1.9.1") { changing = true }
implementation "com.android.support:multidex:1.0.1"

在这里插入图片描述

具体的可以参考 tinker 中的demo中的build.gradle文件。

3: copy demo中的代码到自己的工程中。

在这里插入图片描述

4:添加权限

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

经过上面的步骤,前面的工作是差不多集成完了,但是build的时候 会出现很多问题, 在build出现错误时,请看下面的常见错误。

现在就写代码来测试下。

1 : 界面就两个按钮 和textview结果显示 , 长这样。

在这里插入图片描述

2:点击“写入pitch文件”执行的代码

 public void doHotFix(Context context) throws IllegalAccessException, NoSuchFieldException, ClassNotFoundException {
        if (context == null) {
            return;
        }
        mContext=context;
        OkHttpClient client=new OkHttpClient();
        Request request= new Request.Builder().url(url).get().build();
        Call call=client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("TAG", "onFailure: " );
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                Log.e("51app", "onSuccess");
                FileOutputStream fos = null;
                try {
                    String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
                    File apkFile = new File(sdPath, "patch_signed_7zip");
                    Log.e("51app", "size==" + apkFile.getTotalSpace());
                    if (apkFile.exists()) {
                        apkFile.delete();
                    }
                    apkFile.createNewFile();
                    fos = new FileOutputStream(apkFile);
                    fos.write(response.body().bytes());
                }catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                        Log.e("51app", "downloadPatch  IOException:");
                        e.printStackTrace();
                    }
                }
            }
        });
         //加载补丁包 
         TinkerInstaller.onReceiveUpgradePatch(MainActivity.this, Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip");
    }

代码的功能就是从服务器获取patch_signed_7zip文件,然后写入到本地, 在调用Tinker中的方法来修复。怎么生成这个差量文件patch_signed_7zip 下面会说到。

3: 点击“计算获取结果” 按钮 执行的代码

btn_result.setOnClickListener(new View.OnClickListener() {
    @Override
 	public void onClick(View v) {
	int a=12;
	int b=0;
	int result=a/b;
	tv_result.setText(result);
	}
});

点击执行的时候 ,肯定是崩溃的。会抛ArithmeticException divide by Zero异常。

4: 在activity生命周期方法中的onPause和onResume 调用tinker中的接口。

@Override
protected void onResume() {
    super.onResume();
    Utils.setBackground(false);
}

@Override
protected void onPause() {
    super.onPause();
    Utils.setBackground(true);
}

5: 生成基准包, 双击这个。也可以直接运行生成 然后在build目录下会生成,

在这里插入图片描述
在这里插入图片描述

安装下这个基准包,然后点击’获取结果按钮‘ 程序会崩溃

在这里插入图片描述

6:修改app的gradle文件app/build.gradle

在这里插入图片描述

7:修复那个基准包的异常,点击“计算获取结果” 按钮 执行的代码

 btn_result.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int a=12;
            int b=0;
            if (b==0){
                tv_result.setText("除数为0拉");
                return;
            }
            int result=a/b;
            tv_result.setText(result);
        }
    });

除数为0 时 直接return。 就不会崩溃了。

8: 生成差量包, 双击tinkerPatchDebug。 然后在该build下的目录生成。

在这里插入图片描述
在这里插入图片描述

  1. patch_signed.apk 签过名的
  2. patch_unsigned.apk 未签过名的
  3. patch_signed_7zip.apk 经过压缩的签名过的包

然后把patch_signed_7zip.apk 这个文件放在服务器上。 就可以测试了。 (我测试时把这个名字该了), 还是运行那个基准包。

在这里插入图片描述

可以看到我们首先点击’计算获取结果‘是会崩溃的, 然后我们点击’‘
写入pitch文件 如果成功会有success提示 失败的话也会又提示 现在我们看到succeed 说明已经合成成功了为什么还是崩溃呢。
原因是tinker不是立即生效的。

在这里插入图片描述

合成成功后,我们手动杀掉这个应用的进程,然后再打开 点击“获取计算结果” 就不会崩溃了,说明热更新更能集成完毕。

常见问题

1 :再生成差量包时 versioncode 需要+1 不然合成的时 会失败。

在这里插入图片描述

2:如果在生成差量文件时 build出现异常导致 生成失败的话 就把这个值设置为true

在这里插入图片描述
3:tinkerid 我的是设置为 git的版本号。 也可以设置为 版本号。 保持唯一性, 不然的话 build会失败。

在这里插入图片描述
4: 关掉androidsudio 中的 install run 功能。 不然也会build失败
在这里插入图片描述
感谢关注我的公众号
在这里插入图片描述

参考文档

Tinker接入指南 :https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97

常见问题 : https://github.com/Tencent/tinker/wiki/Tinker-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

热修复原理 :

https://blog.csdn.net/csdn_lqr/article/details/78534065

https://blog.csdn.net/itermeng/article/details/79350945

https://blog.csdn.net/itermeng/article/details/79362042

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!