打造Android万能的软件更新库

xiaoxiao2021-02-28  13

今日科技快讯

阿里星球今天在苹果商店发布的更新动态显示,其将在近期停止APP内的音乐服务,用户可以通过新版本内的指引和说明,导出本地音乐。这意味着上线八个月后,阿里星球做出了一个重大决定:停止音乐服务后,这款由天天动听改版而来、承载了阿里音乐铁三角期望的APP,将彻底与音乐播放器功能告别。

作为宋柯、高晓松以及何炅加盟阿里音乐后准备了大半年推出的平台,阿里星球承载了阿里音乐铁三角对音乐业务的重要期望,但从结果来看并不如人意。上线之初,阿里星球便遭遇大量用户差评。

作者简介

本篇来自 hcy 的投稿,分享了他自己封装的软件更新工具。希望能帮助到有需要的朋友。

hcy 的博客地址:

http://blog.csdn.net/huang_cai_yuan

概述

软件更新功能可以说是APP的标配。以前实现这个功能的时候,自己一行一行代码重复撸,浪费时间。所以我决定实现一个万能的可复用的更新库。让它支持增量更新、全量更新、静默安装、普通方式安装、可以自定义UI。下面就来介绍一下我实现这个库的主要技术点:增量更新、静默安装及如何封装。

软件增量更新处理流程

服务端处理流程

1. 验证请求的合法性。 

2. 如果请求不合法(比如请求是模拟的,非客户端发出的),则拒绝服务。 

3. 如果请求合法,获取versionCode等信息,根据versionCode判断软件是否更新。 

4. 如果不需要更新,则返回对应信息。 

5. 如果需要更新,获取与versionCode对应的客户端文件的MD5,判断该MD5值是否在历史版本文件的MD5列表中,如果在说明支持增量更新。 

6. 如果不支持增量更新,则返回完整apk文件的下载链接。 

7. 如果支持增量更新,判断对应的patch文件是否存在。 

8. 如果对应的patch文件不存在,调用脚本程序生成对应的patch文件,并返回该patch文件的下载链接。 

9. 如果对应的patch文件存在,则返回该patch文件的下载链接。

客户端处理流程

1. 收集apk的基本信息,向服务端发送更新请求。 

2. 如果没有更新,则做对应的提示操作。 

3. 如果有更新,判断是否是增量更新还是全量更新。 

4. 如果是全量更新,则下载对应的apk文件,展示相应的UI,安装apk即可。 

5. 如果是增量更新,则下载对应的patch文件,展示相应的UI,然后提取客户端的apk文件到指定目录并与patch文件合并成一个新的apk文件,判断新合成的apk文件是否与从服务端获取的完整的apk文件MD5的值一致,若一致说明合成成功,安装新合成的apk文件即可,若不一致说明合成失败,进行安装失败的提示。

增量更新的实现

通过上面的处理流程分析,我们发现实现增量更新的难点主要在于patch文件的生成、新apk文件的合成这两个部分。这里借助开源的bsdiff来实现这两部分的功能。

1. 下载二进制差分、合并工具

增量更新的实现用到第三方库

bsdiff

http://www.daemonology.net/bsdiff

该库依赖:

bzip2

http://www.bzip.org/downloads.html

bsdiff 目前支持 Linux、Windows,同时也有 Python 版本的源码。

2. 服务端patch文件的生成

服务端可以根据需要,选择对应的版本进行 patch文件 的生成,比如 Windows版本 的生成方式如下: 

同时按住 Shift+右键,选择“在此处打开命令窗口”,执行命令 bsdiff old.apk new.apk patch.patch 即可生成patch包,至于脚本怎么执行这些命令,请读者自行发挥。

3. 客户端新apk的合成实现

点击条目1中的链接,下载linux版本的源代码,同时下载bzip2的源代码,文件目录结构如下:

接着将bsdiff.c、bspatch.c文件中的main方法改成 diff、patch

然后编写jni代码,调用bsdiff和bspatch的diff、patch方法

接下来,在外层的 Android.mk 文件中编写 makefile脚本(gradle里面编译jni我不熟,哈哈哈,还是makefile用着习惯),将bsdiff、bzip2编译成静态库,同时引入 子目录的Android.mk文件。

在 jni_bsdiff目录 下面的 Android.mk 文件中编写生成我们要用的动态库的脚本如下

再接下来,在build.gradle里面编写编译脚本即可:

如果不出意外我们的 libbsdiff_utils.so 就可以生成了。然后我们编写Java层的调用代码:

新apk文件的合成我们要用到的是patch方法,它的参数 oldPath 表示 当前apk的文件路径,newPath 表示 合成后的apk文件路径,patchPath 则为 下载的增量包的路径。

oldPath 的取值,比较稳妥的做法是把当前安装的apk文件拷贝到一个可读可写的目录,防止bspatch对已安装的apk文件产生破坏。附上获取当前apk文件的路径的代码:

静默安装实现

静默安装这里采用 pm install 命令实现,因此应用需要获取到Root权限才能执行成功。

封装

为了打造一个可复用的软件更新库,这里根据软件更新的流程抽象了五个接口,流程与接口的对应关系如下: 

更新检测(UpdateChecker) 

更新检测后的UI提示(UpdateCheckUIHandler) 

更新文件下载(Downloader) 

文件下载时的UI提示(DownloadUIHandler) 

安装文件(AppInstaller) 

如果使用者发现哪一步不符合自己的需求,只要实现这个步骤的接口并注入到全局配置中即可,从而实现“万能”的软件更新功能。 

具体实现,请参照源码:

https://github.com/Money888/LibUpgrade.git

更新库的使用

第一步,在 Application.onCreate 方法中进行初始化

@Overridepublic void onCreate() {    super.onCreate();    LibUpgradeInitializer.init(this); }

第二步,配置更新库功能

第三步,启用更新检查功能

//此处的Context默认必须为ActivityUpdater.getInstance().check(this);

自定义功能扩展使用

1. 增量更新

2. 全量更新

3. 强制更新

4. 普通安装模式

5. 静默安装模式

6. 修改更新时的提示UI

7. 修改文件下载时的UI

其它二进制差分及合并工具

xdelta3

http://xdelta.org/xdelta3.html

javaxdelta

http://javaxdelta.sourceforge.net

courgette

https://chromium.googlesource.com/chromium/src/courgette

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

如果觉得有帮助可赞赏作者

赞赏

人赞赏

转载请注明原文地址: https://www.6miu.com/read-1250356.html

最新回复(0)