Android热更新初探,Bugly热更新的购并和平运动用(让您的运用轻便具备热更新技能)

发布时间:2019-09-10  栏目:Python  评论:0 Comments

介绍

在介绍Bugly从前,必要先向大家简要介绍下部分热更新的有关内容。当前市集的热补丁方案有非常多,当中相比出名的有Ali的AndFix、美团的罗布ust以及QZone的超级补丁方案。但它们都设有不可能化解的主题素材,那也是Tinker面世的源委。Tinker近期已运营在微信的数亿Android设备上,相对于任何热更新方案,Tinker绝对相比完美。

参考:
微信Tinker
Bugly
Android热更新使用指南

什么是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体积 较大 较小 较小 较小
成功率 较高 较高 一般 最高

总的看:

  1. AndFix作为native实施方案,首先面前碰着的是安生服业与包容性难点,更主要的是它不能够兑现类替换,它是急需大量外加的开辟费用的;

  2. 罗布ust包容性与成功率较高,然而它与AndFix同样,无法新添变量与类只可以用做的bugFix方案;

  3. Qzone方案得以达成发布产品效果,不过它首要难题是插桩带来Dalvik的品质难题,以及为了解决Art下内部存款和储蓄器地址难题而致使补丁包急迅增大的。

有了Bugly帮助大家集成,那么我们就不须求过多去关爱Tinker是什么样安插的,因为其配置太勤奋了。只是在境遇有些专程的标题时,大家不要紧去看看微信Tinker的拉拉扯扯文档!

Tinker的已知难点

  1. Tinker不协理修改AndroidManifest.xml,Tinker不支持新扩张四大组件(1.9.0帮助新添非export的Activity);

  2. 出于Google Play的开垦者条约限制,不建议在GP路子动态更新代码

  3. 在Android N上,补丁对运用运营时间有一线的震慑;

  4. 不支持部分三星(Samsung)android-21机型,加载补丁时会主动抛出”TinkerRuntimeException:checkDexInstall
    failed”;

  5. 对此能源替换,不帮忙修改remoteView。比如transition动画,notification
    icon以及桌面Logo。

率先步:在总工程师程的build.grade上面增加正视

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

Tinker越多介绍

对于tinker的详实介绍,感兴趣的可此前往查看,地址:

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

第二步:在当前Modle的build.grade中集成SDK

dependencies {

          compile "com.android.support:multidex:1.0.1" // 多dex配置
          compile 'com.tencent.bugly:crashreport_upgrade:latest.release' // 升级SDK
}

并在最上边投入依赖插件脚本

apply from: 'tinker-support.gradle'

那些剧本必要和谐在日前Model的根目录下开创,要和build.grade在平等文件夹

图片 1

QQ截图20170211100428.png

tinker-support.gradle里面包车型地铁内容如下:

apply plugin: 'com.tencent.bugly.tinker-support'

def bakPath = file("${buildDir}/bakApk/")

/**
 * 此处填写每次构建生成的基准包目录
 */
def baseApkDir = "app-0208-15-10-00"

/**
 * 对于插件各参数的详细解析请参考
 */
tinkerSupport {

    // 开启tinker-support插件,默认值true
    enable = true

    // 指定归档目录,默认值当前module的子目录tinker
    autoBackupApkDir = "${bakPath}"

    // 是否启用覆盖tinkerPatch配置功能,默认值false
    // 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
    overrideTinkerPatchConfiguration = true

    // 编译补丁包时,必需指定基线版本的apk,默认值为空
    // 如果为空,则表示不是进行补丁包的编译
    // @{link tinkerPatch.oldApk }
    baseApk = "${bakPath}/${baseApkDir}/app-release.apk"

    // 对应tinker插件applyMapping
    baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"

    // 对应tinker插件applyResourceMapping
    baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"

    // 构建基准包和补丁包都要指定不同的tinkerId,并且必须保证唯一性
    tinkerId = "base-1.0.1"

    // 构建多渠道补丁时使用
    // buildAllFlavorsDir = "${bakPath}/${baseApkDir}"

    // 是否开启反射Application模式
    enableProxyApplication = false

}

/**
 * 一般来说,我们无需对下面的参数做任何的修改
 * 对于各参数的详细介绍请参考:
 * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
 */
tinkerPatch {
    //oldApk ="${bakPath}/${appName}/app-release.apk"
    ignoreWarning = false
    useSign = true
    dex {
        dexMode = "jar"
        pattern = ["classes*.dex"]
        loader = []
    }
    lib {
        pattern = ["lib/*/*.so"]
    }

    res {
        pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
        ignoreChange = []
        largeModSize = 100
    }

    packageConfig {
    }
    sevenZip {
        zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
//        path = "/usr/local/bin/7za"
    }
    buildConfig {
        keepDexApply = false
        //tinkerId = "1.0.1-base"
        //applyMapping = "${bakPath}/${appName}/app-release-mapping.txt" //  可选,设置mapping文件,建议保持旧apk的proguard混淆方式
        //applyResourceMapping = "${bakPath}/${appName}/app-release-R.txt" // 可选,设置R.txt文件,通过旧apk文件保持ResId的分配
    }
}

更详细的配置项参谋tinker-support配置表明

当心那个文件中配置了enableProxyApplication = false
乐趣就是是不是展开反射Application方式,默感觉false
那是Tinker推荐的对接方式,一定水平上会扩展接入开支,但装有更加好的包容性。

Bugly的介绍

腾讯Bugly,是Tencent集团为移动开辟者开放的劳动之一,面向移动开荒者提供标准的
Crash 监察和控制、崩溃分析等身分追踪服务。Bugly
能援救移动网络开拓者更及时地觉察掌握控制非常,更周密的刺探定位特别,更加高效的修补消除那多少个。

Bugly近期包蕴三大服务:

  1. 特别申报;
  2. 营业计算;
  3. 使用晋级(富含全量进级和热更新)。

第三步:初始化SDK

分二种情景来扩充初阶化

Bugly的热更新

热更新才能是Bugly为搞定开辟者紧迫修复线上bug,而无需另行发版让顾客无感知就会把难点修复的一项技术。Bugly近年来采纳微信Tinker的开源方案,开辟者只供给集成我们提供的SDK就能够实现活动下载补丁包、合成、并选取补丁的机能,大家也提供了热更新管理后台让开拓者对各类版本补丁举办管理。

情况一(推荐):enableProxyApplication = false

亟待我们自定义的MyApplication承袭TinkerApplication

public class SampleApplication extends TinkerApplication {
    public SampleApplication() {
        super(ShareConstants.TINKER_ENABLE_ALL, "xxx.xxx.SampleApplicationLike",
                "com.tencent.tinker.loader.TinkerLoader", false);
    }
}

留意:那些类集成TinkerApplication类,那之中不做任何操作,全体Application的代码都会停放ApplicationLike承接类个中
三个参数分析
参数1:tinkerFlags 表示Tinker帮忙的品类 dex only、library only or all
suuport,default: TINKE福特Explorer_ENABLE_ALL
参数2:delegateClassName Application代理类
这里填写您自定义的ApplicationLike
参数3:loaderClassName Tinker的加载器,使用暗许就能够
参数4:tinkerLoadVerifyFlag 加载dex或许lib是不是表明md5,默许为false

此间必要再一次写三个ApplicationLike来承袭DefaultApplicationLike

public class SampleApplicationLike extends DefaultApplicationLike {

    public static final String TAG = "Tinker.SampleApplicationLike";

    public SampleApplicationLike(Application application, int tinkerFlags,
            boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime,
            long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
    }


    @Override
    public void onCreate() {
        super.onCreate();
        // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
        // 调试时,将第三个参数改为true
        Bugly.init(getApplication(), "900029763", false);
    }


    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    public void onBaseContextAttached(Context base) {
        super.onBaseContextAttached(base);
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base);

        // 安装tinker
        // TinkerManager.installTinker(this); 替换成下面Bugly提供的方法
        Beta.installTinker(this);
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
        getApplication().registerActivityLifecycleCallbacks(callbacks);
    }

}

注意:这里发现合土耳其(Turkey)语档的三个bug,在onCreate中实行了Bugly.init(this,
“玖仟29763”,
false);也便是Bugly调节和测量检验的起首化,可是当中第贰个参数是要传播上下文的,而SampleApplicationLike
只是叁个抽象类的兑现类。这段应该献身MyApplication的OnCreate()方法中才对,所以这里注释掉了!
(其实在此地能够运用getApplication()来得到上下文替换this,感谢小巫的唤醒。)

干什么使用Bugly热更新?

  • 无需关切Tinker是怎么着合成补丁的

  • 不要自个儿搭建补丁管理后台

  • 不必思考后台下发补丁攻略的别样业务

  • 毋庸思索补丁下载合成的机缘,处理后台下发的计策

  • Bugly提供了尤其便于集成Tinker的办法

  • Bugly通过HTTPS及签字校验等体制保险补丁下发的安全性

  • 加上的颁发维度调控,有效调节补丁影响范围

  • Bugly提供了选拔晋级一条龙实施方案

情况二(简单):enableProxyApplication = true
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
        // 调试时,将第三个参数改为true
        Bugly.init(this, "900029763", false);
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base);


        // 安装tinker
        Beta.installTinker();
    }

}

注:无须你改造Application,首若是为了缩小接入花费,大家插件会动态替换AndroidMinifest文件中的Application为咱们定义好用于反射真实Application的类(要求你接入SDK
1.2.2版本 和 插件版本 1.0.3之上)。

Bugly热更新SDK的集成

集成Bugly热更新的详尽操作能够仿照效法官方网址的文档:

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

  1. 工程根目录build.gradle增多tinker-support插件重视;

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

  3. app目录下新建tinker-support.gradle文本,文件的剧情文书档案有提供;

  4. 初叶化SDK,更换application,即便也得以不改造application,但是包容性恐怕会产出难题,官方推荐更改application;

  5. AndroidManifest.xml安插相关权限,借使仅仅只是使用热更新而不须要利用到全量晋级功效,无需布置BetaActivity和FileProvider

  6. 模糊配置,在proguard-rules.pro文件中增多Bugly的模糊准绳

第四步:AndroidManifest.xml的配置

集成热更新所碰到的相干难题:

  • 文档中提及使用插件的流行版本能够通过应用lastest.release拉取,如图:

图片 2image

但自个儿增多注重的时候,如下:

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那项计划,根据文书档案来打补丁的时候,会现出如下错误:

图片 3image

看了错误提醒,老是提醒笔者说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.673Created-By: YaFixYaPatchType: 2VersionName: 1.0.5VersionCode: 5From: 1.0.5-1121-11-36-06To: 1.0.5-1121-11-37-15

From 是基准包的tinkerIdTo 是现阶段补丁包的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}

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

VERSION_NAME=1.0.5VERSION_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") }}
1.权力配置
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

留意:如若您也想行使Bugly升级功用,你无法不要进行2、3项的配备,而一旦您只想利用热更新才具,你只必要配置权力就能够。

Bugly Q&A

到这边Bugly热更新的有关介绍就到此结束了,在此处向大家简介了Bugly集成是采纳中遇到的主题素材和连锁的建议,官方也提供了大面积难题消除的介绍:

Bugly Android 热更新常见难题

倘诺中间找不到您想要的,能够联系他们的客服的QQ,但是客服大致不应对,有一点点无可奈何,客服QQ自动还原推荐去他们的论坛留言,可是开采该论坛禁止注册了,有一些悲催。几番波折后,终于在他们的博客园博客园上找到了盼望:

图片 4image

发觉了他们提供能力匡助的QQ研究群,群号为:
130979883,今后已经加入了群里,向Bugly的能力人员询问了和煦的有关疑问。

2. Activity配置
<activity
    android:name="com.tencent.bugly.beta.ui.BetaActivity"
    android:theme="@android:style/Theme.Translucent" />

Demo源码

https://github.com/chaychan/BuglyHotFixDemo

3. 配置FileProvider

瞩目:若是您想包容Android
N恐怕以上的装置,必要求在AndroidManifest.xml文件中配置FileProvider来访谈分享路线的文书。假如您采纳的第三方库也布置了同等的FileProvider,你要求将第三方库配置的路线copy到我们布置的provider_path文件下。

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

${applicationId}请替换为您的包名,举个例子com.bugly.upgrade.demo。这里要留心一下,FileProvider类是在support-v4包中的,检查你的工程是还是不是引进该类库。

在res目录新建xml文件夹,创造provider_paths.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
    <external-path name="beta_external_path" path="Download/"/>
    <!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
    <external-path name="beta_external_files_path" path="Android/data/"/>
</paths>

此地配置的八个外表存款和储蓄路线是升迁SDK下载的文书或许存在的门径,一定要依照地方格式配置,不然大概会合世错误。

帮衬和鞭挞

一经你开心作者的作品的话,能够关切本身的博客,谢谢我们一如既往给自己的支撑和鞭挞,你们的每便喜欢和打赏,使本人写作品更有重力。

第五步:混淆配置 (未有歪曲的能够忽略)

为了制止混淆SDK,在Proguard混淆文件中扩展以下配置:

-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}

倘使你采纳了support-v4包,你还索要配备以下混淆准绳:

-keep class android.support.**{*;}

到那边大约就停止了,其实配置真的很麻烦,都是Bugly帮大家简化了好些个地点了。
下边就是我们同心协力去实行的时刻了:
热更新实施

留下评论

网站地图xml地图