Android热更新介绍,Bugly热更新的集成和使用

1、为什么要用热更新
      开发人员一定深有体会,上线的app突然发现一个bug影响用户使用,就需要重新打包App、测试、向各个应用市场和渠道换包、提示用户升级、用户下载、覆盖安装等步骤,用户还会抱怨怎么又升级了,频繁升级对用户体验也不好。就想到能不能像服务器哪样,如果有问题就替换某个文件重启,用户就可以继续使用了。这就衍生出热修复概念产生。

2、什么是热修复
      热修复通俗说就是打补丁,让用户在无感的情况下更新,修复不用重新发版。

3、热修复原理

      在热修复出现之前,一个已经上线的app中如果出现了bug,即使是一个非常小的bug,不及时更新的话有可能存在风险,若要及时更新就得将app重新打包发布到应用市场后,让用户再一次下载,这样就大大降低了用户体验,当热修复出现之后,这样的问题就不再是问题了。

目前较火的热修复方案大致分为两派,分别是:

  1. 阿里系:DeXposed、andfix:从底层二进制入手(c语言)。
  2. 腾讯系:tinker:从java加载机制入手。

其实,不管是哪种热修复方案,肯定是如下几个步骤:

  1. 下发补丁(内含修复好的class)到用户手机,即让app从服务器上下载(网络传输)
  2. app通过"某种方式",使补丁中的class被app调用(本地更新)

其中第二种方式,与安卓的类加载过程切入,过程简介如下:

安卓的类加载器在加载一个类时会先从自身DexPathList对象中的Element数组中获取(Element[] dexElements)到对应的类,之后再加载。采用的是数组遍历的方式,不过注意,遍历出来的是一个个的dex文件。

  在for循环中,首先遍历出来的是dex文件,然后再是从dex文件中获取class,所以,我们只要让修复好的class打包成一个dex文件,放于Element数组的第一个元素,这样就能保证获取到的class是最新修复好的class了(当然,有bug的class也是存在的,不过是放在了Element数组的最后一个元素中,所以没有机会被拿到而已)。

更多可参考这篇文章。https://www.jianshu.com/p/cb1f0702d59f

 

4、什么是Tinker
  Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。

                 Tinker    QZone    AndFix    Robust
类替换           yes         yes          no          no
So替换          yes         no           no           no
资源替换       yes        yes           no          no
全平台支持    yes        yes         yes         yes
即时生效       no          no           yes         yes
性能损耗      较小      较大         较小       较小
补丁包大小   较小     较大         一般       一般
开发透明       yes      yes            no          no
复杂度         较低      较低         复杂       复杂
gradle支持   yes         no            no         no
Rom体积     较大      较小         较小       较小
成功率        较高      较高         一般        最高


总的来说:

AndFix作为native解决方案,首先面临的是稳定性与兼容性问题,更重要的是它无法实现类替换,它是需要大量额外的开发成本的;

Robust兼容性与成功率较高,但是它与AndFix一样,无法新增变量与类只能用做的bugFix方案;

Qzone方案可以做到发布产品功能,但是它主要问题是插桩带来Dalvik的性能问题,以及为了解决Art下内存地址问题而导致补丁包急速增大的。

Tinker的已知问题
*Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件(1.9.0支持新增非export的Activity);

*由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码

*在Android N上,补丁对应用启动时间有轻微的影响;

*不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed";

*对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。

5、Tinker更多介绍
  对于tinker的详细介绍,感兴趣的可以前往查看,地址:

  https://github.com/Tencent/tinker/wiki

6、Bugly的介绍
  腾讯 Bugly,是腾讯公司为移动开发者开放的服务之一,面向移动开发者提供专业的 Crash 监控、崩溃分析等质量跟踪服务。Bugly 能帮助移动互联网开发者更及时地发现掌控异常,更全面的了解定位异常,更高效的修复解决异常。

Bugly目前包括三大服务:

   * 异常上报;
   *运营统计;
   * 应用升级(包括全量升级和热更新)。


Bugly的热更新
  热更新能力是Bugly为解决开发者紧急修复线上bug,而无需重新发版让用户无感知就能把问题修复的一项能力。Bugly目前采用微信Tinker的开源方案,开发者只需要集成我们提供的SDK就可以实现自动下载补丁包、合成、并应用补丁的功能,我们也提供了热更新管理后台让开发者对每个版本补丁进行管理。

为什么使用Bugly热更新?
*无需关注Tinker是如何合成补丁的;

*无需自己搭建补丁管理后台;

*无需考虑后台下发补丁策略的任何事情;

*无需考虑补丁下载合成的时机,处理后台下发的策略;

*Bugly提供了更加方便集成Tinker的方式;

*Bugly通过HTTPS及签名校验等机制保障补丁下发的安全性;

*丰富的下发维度控制,有效控制补丁影响范围;

*Bugly提供了应用升级一站式解决方案;

 

Bugly热更新SDK的集成
集成Bugly热更新的详细操作可以参考官网的文档:

https://bugly.qq.com/docs/user-guide/instruction-manual-android-hotfix/?v=20171109131920

在这里就不一步一步地结合如何集成SDK,总的来说有一下几个步骤:
工程根目录build.gradle添加tinker-support插件依赖;

app module的build.gradle添加SDK依赖;

在app目录下新建tinker-support.gradle文件,文件的内容文档有提供;

初始化SDK,改造application,虽然也可以不改造application,但是兼容性可能会出现问题,官方推荐改造application;

AndroidManifest.xml配置相关权限,如果仅仅只是使用热更新而不需要使用到全量升级功能,不需要配置BetaActivity和FileProvider。

混淆配置,在proguard-rules.pro文件中添加Bugly的混淆规则。

集成热更新所遇到的相关问题:
文档中提及使用插件的最新版本可以通过使用lastest.release拉取,如图:


但我添加依赖的时候,如下:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // tinkersupport插件, 其中lastest.release指拉取最新版本,也可以指定明确版本号,例如1.0.4
        classpath "com.tencent.bugly:tinker-support:lastest.release"
    }
}


报了找不到该依赖的错误,原来是文档写错了,lastest应改成latest才对。

tinker-support.gradle中缺少supportHotplugComponent这项配置导致打补丁包的时候出现错误
  视频介绍和文档中都没有提及到tinker-support.gradle文件tinkerSupport { }中需要添加多supportHotplugComponent这项配置,按照文档来打补丁的时候,会出现如下错误:

看了错误提示,老是提示我说manifest was changed,可是我根本没有改动到manifest,一直很纳闷,直到看了demo后,才发现需要在tinkerSupport { }中,添加supportHotplugComponent这项配置,代码如下:

tinkerSupport { 
    
    ...
    
    supportHotplugComponent = true
    
}


thinkerId 的指定
  thinkerId需要是唯一的,在生成基准包和补丁包时都需要改动,官方推荐时间用git版本号或版本名生成,这里我自己使用的是versionName_MM-dd-HH-mm-ss这种格式,版本名+时间戳,比如1.0.5-1121-11-33-20,这和bakApk下生成基准包目录的时间戳类似,它是app-1121-11-33-20,这样查看起来一路了然,查看补丁包的YAPATCH文件也很清晰:

Created-Time: 2017-11-21 11:37:15.673
Created-By: YaFix(1.1)
YaPatchType: 2
VersionName: 1.0.5
VersionCode: 5
From: 1.0.5-1121-11-36-06
To: 1.0.5-1121-11-37-15


From 是基准包的tinkerId
To 是当前补丁包的tinkerId

生成上述格式tinkerId的代码如下:

tinkerSupport { 
    
    ...
    
    tinkerId = "${verName()}-${buildTime()}"
    
    ...
    
}

//获取版本名
def verName() {
    def versionPropsFile = file("../version.properties")
    if (versionPropsFile.canRead()) {
        Properties versionProps = new Properties()
        versionProps.load(new FileInputStream(versionPropsFile))

        return versionProps['VERSION_NAME']
    } else {
        throw new GradleException("Could not read gradle.properties")
    }
}

//获取构建时间
def buildTime() {
    return new Date().format("MMdd-HH-mm-ss", TimeZone.getTimeZone("GMT+8"))
}

需要在工程根目录下,和gradle.properties文件同目录下,新建version.properties文件,用于保存当前app的versionCode和versionName,文件的内容:


VERSION_NAME=1.0.5
VERSION_CODE=4


既然将versionCode和versionName配置在properties文件中,那么app module的gradle文件中,defaultConfig{}中指定版本名和版本号直接使用该配置


android {
  
    ...

    defaultConfig {
        ...
        
        versionCode verCode()
        versionName verName()
       
       ...
    }
 }
获取版本号的方法verCode(),代码如下:


//获取版本号
def verCode() {
    def versionPropsFile = file("../version.properties")
    if (versionPropsFile.canRead()) {
        Properties versionProps = new Properties()
        versionProps.load(new FileInputStream(versionPropsFile))

        def int verCode = versionProps['VERSION_CODE'].toInteger()
        return verCode;
    } else {
        throw new GradleException("Could not read gradle.properties")
    }
}


Bugly Q&A
  到这里Bugly热更新的相关介绍就到此为止了,在这里向大家简单介绍了Bugly集成是使用中遇到的问题和相关的建议,官方也提供了常见问题解决的介绍:

   Bugly Android 热更新常见问题

如果里面找不到你想要的,可以联系他们的客服的QQ,但是客服几乎不回答,有点无奈,客服QQ自动回复推荐去他们的论坛留言,可是发现该论坛禁止注册了,有点悲催。几番波折后,终于在他们的新浪微博上找到了希望:

发现了他们提供技术支持的QQ讨论群,群号为: 130979883,现在已经加入了群里,向Bugly的技术人员询问了自己的相关疑问。
--------------------- 
作者:ChayChan 
原文:https://blog.csdn.net/Chay_Chan/article/details/78591621 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章