Android-Tinker 腾讯bugly热修复踩坑

本知识点只是个人见解,具体知识及使用请查阅官网,以免被误导,同时大家可以对此文发表自己的见解。

不得不说,接入第三方的时候,稍微不注意,坑就很多! 所以要注意很多细节在里面!

之前写了个适配8.0的方案 https://blog.csdn.net/yang1349day/article/details/80016607 后来适配的问题还是很多,于是接了腾讯的bugly.不得不说bugly的接入文档写的非常好

本文只讲接入的坑,具体接入步骤自己去官网查看,官网地址 https://bugly.qq.com/docs/user-guide/instruction-manual-android-hotfix/?v=20170912151050


1 打好path包之后,上传到bugly后台显示如图:


首先你看下这个官方视频http://v.qq.com/boke/gplay/9f3b4b1232819f453becd2356a3493c4_bme000301803d13_5_e0385shcfzm.html  如果你看了,可以免过,继续看下面:

我总结了使用过程中的一些经验:

1 打基准包的时候,设置的tinkerId的时候,优先设置自己版本号,记住此处的版本号一定要比用户正在使用的要大. 比如市场上的版本号是1.0.9,如果市场上的1.0.9版本设置过了基准包为base-1.0.9 那么release的patch包版本号也设置成patch-1.1.0 ,如果市场上的版本是1.0.9但是没有设置过基准包,则先生成基准包为base-1.1.0, 设置好了之后,把这个基准包在手机上面安装一下,然后仔细观察CrashReport的log日志,如果联网成功,buglu后台就会知道你这个基准包的版本了. 然后生成release的patch包版本号也设置成patch-1.1.0.

注意: 一定要观察log, 同时最好在application处设置监听,如下代码:

private void initializeBugly() {
        Beta.enableHotfix = true;
        // 设置是否自动下载补丁,默认为true
        Beta.canAutoDownloadPatch = true;
        // 设置是否自动合成补丁,默认为true
        Beta.canAutoPatch = true;
        // 设置是否提示用户重启,默认为false
        Beta.canNotifyUserRestart = true;
        // 补丁回调接口
        Beta.betaPatchListener = new BetaPatchListener() {
            @Override
            public void onPatchReceived(String patchFile) {
//                Toast.makeText(getApplication(), "补丁下载地址" + patchFile, Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onPatchReceived: "+"补丁下载地址" + patchFile);
            }

            @Override
            public void onDownloadReceived(long savedLength, long totalLength) {
//                Toast.makeText(getApplication(),
//                        String.format(Locale.getDefault(), "%s %d%%",
//                                Beta.strNotificationDownloading,
//                                (int) (totalLength == 0 ? 0 : savedLength * 100 / totalLength)),
//                        Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onDownloadReceived: "+"补丁下载地址" + String.format(Locale.getDefault(), "%s %d%%",
                        Beta.strNotificationDownloading,
                        (int) (totalLength == 0 ? 0 : savedLength * 100 / totalLength)));
            }

            @Override
            public void onDownloadSuccess(String msg) {
//                Toast.makeText(getApplication(), "补丁下载成功", Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onDownloadSuccess: "+"补丁下载成功");
            }

            @Override
            public void onDownloadFailure(String msg) {
//                Toast.makeText(getApplication(), "补丁下载失败", Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onDownloadFailure: "+"补丁下载失败");
            }

            @Override
            public void onApplySuccess(String msg) {
//                Toast.makeText(getApplication(), "补丁应用成功", Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onApplySuccess: "+"补丁应用成功");
            }

            @Override
            public void onApplyFailure(String msg) {
//                Toast.makeText(getApplication(), "补丁应用失败", Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onApplyFailure: "+"补丁应用失败");
            }

            @Override
            public void onPatchRollback() {
                Timber.tag("CrashReport");
                Timber.e("onPatchRollback: "+"补丁应用失败");
            }
        };

        /**
         *  全量升级状态回调
         */
        Beta.upgradeStateListener = new UpgradeStateListener() {
            @Override
            public void onUpgradeFailed(boolean b) {
                Timber.tag("CrashReport");
                Timber.e("onUpgradeFailed: "+"全量升级状态回调"+b);
            }

            @Override
            public void onUpgradeSuccess(boolean b) {
                Timber.tag("CrashReport");
                Timber.e("onUpgradeSuccess: "+"全量升级状态回调"+b);
            }

            @Override
            public void onUpgradeNoVersion(boolean b) {
//                Toast.makeText(DidiApplicationLike.this.getApplication(), "最新版本", Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onUpgradeNoVersion: "+"全量升级状态回调"+b);
            }

            @Override
            public void onUpgrading(boolean b) {
//                Toast.makeText(DidiApplicationLike.this.getApplication(), "onUpgrading", Toast.LENGTH_SHORT).show();
                Timber.tag("CrashReport");
                Timber.e("onUpgrading: "+"全量升级状态回调"+b);
            }

            @Override
            public void onDownloadCompleted(boolean b) {
                Timber.tag("CrashReport");
                Timber.e("onDownloadCompleted: "+"全量升级状态回调"+b);
            }
        };

        // 设置开发设备,默认为false,上传补丁如果下发范围指定为“开发设备”,需要调用此接口来标识开发设备
        Bugly.setIsDevelopmentDevice(getApplication(), true); //在发布正式版本的时候需要关掉,不然发布新的patch包的时候,测试都没法去测试!
        // 多渠道需求塞入
        // String channel = WalleChannelReader.getChannel(getApplication());
        // Bugly.setAppChannel(getApplication(), channel);

        // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
        // 调试时,将第三个参数改为true
        Bugly.init(getApplication(), AppConfig.BuglyAppId, AppConfig.ADB);
    }

在测试的时候最好把弹框打开,这样更直观些. 同时把bugly.init第三个参数设置为true,如果没有看到log,请先调试出log后再进行下一步.


2 官网上面展示的是很理想的情况下的bugly配置和修复.但是接入到实际项目可能会有些迷惑如下:

首先来观察下图:


1 目标版本和我们设置的patch版本实际上不一致的哦,不要太纠结. 

2 已激活,已下发之类的其实是有延迟的,所以不要指望会立即生效

3 如果上传版本的时候还是出现未上传基准包,最好先刷新这个页面,让后台即时更新

3 bugly的下载及加载策略(持续更新中...)

bugly接入完毕,但是有个问题,用户进入app的时候立即闪退,导致bugly下载patch包和合并修复不及时,导致bug无法修改。

所以此处涉及到一个合适加载的问题:

1 参考手Q的策略,就是检测到有patch包就进入下载和加载patch页面,当进度条显示加载完毕则自动重启app进入启动页面,这种效果是非常好的。而官方提供给我的则是一个弹窗,提示用户重启,导致无法及时修复bug。那么怎么去仿手Q的加载页面呢? 那就必须要对回调有所理解,要不断的调试才行,调试的时候要把instans run 关掉才能热启动,不用一直用命令行启动哦。此处还在持续更新....

 2 解决不停闪退的办法还有一个,就是使用uncathExceptionHandler,自定义发生异常之后的操作

可以使用的开源框架是---崩溃日志搜集


4 bugly的实践

实际应用中,请注意保存线上发布版本的基准apk包、mapping文件、R.txt文件,如果线上版本有bug,就可以借助我们tinker-support插件进行补丁包的生成。要是删除了基准包,就无法热更新了哦! 同时,发布新的patch包,调试开发者设备的时候需要设置为false

     // 设置开发设备,默认为false,上传补丁如果下发范围指定为“开发设备”,需要调用此接口来标识开发设备
        Bugly.setIsDevelopmentDevice(getApplication(), true); //在发布正式版本的时候需要关掉,不然发布新的patch包的时候,测试都没法去测试!!!
    

2 如下所示,一个模拟器不停的在刷接口,导致的很多的空指针和异常bug,所以直接可以将其拉黑,限制访问

3 持续更新中...



最后,需要注意的是,视频一定要看!!! 而且不要边接入边看,要先看完,然后再接入,不动的再回过去看文档或者视频

.同时,入手的时候,最好先自己做个小demo,然后再接进去自己的项目,这是接入所有第三方的基本套路!


猜你喜欢

转载自blog.csdn.net/yang1349day/article/details/80091895