Android Small框架增量升级方案

news2024/11/8 22:05:51

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Small框架增量升级方案相关的知识,希望对你有一定的参考价值。

背景

随着业务的发展,安装包的体积也在不断的增大,这时候,如果要版本更新,用户不得不去下载完整的安装包。但是如果使用增量升级方案,用户只需要下载新旧版本的差异包,然后在本地合成就行,这样省时省力。我们可以看下某产品使用增量升级时的数据:

  • xxx.2.4.0000.apk 32MB
  • xxx.2.5.0000.apk 28MB
  • 差异包 6.3MB

其中增量包就是上文提到的差异包,可见用户每次升级只需下载差异包就行,省时省力。

原理

其原理就是,我们在服务器端先拿新版本安装包和旧版本安装包进行对比,在生成差异包之后下发,之后客户端根据对应的差异包和本地旧版本安装包合成,便生成了新版本安装包

实现

0x01 下载编译差分合并工具:
apk文件的差分和合并都是使用的开源的二进制比较工具 bsdiff实现,值得注意的是,该工具依赖bizp2这个库。在下载完毕后,直接make便可以编译工具,不过我在一台苹果机器上编译的时候出现了一点问题,那时候make文件没法正确的读取,所以我修改了make文件,读者编译的时候(仅限mac, linux)只需要运行install.sh脚本就行。这部分的代码我已经单独抽出来作为一个repo,读者喜欢可以自行star,然后下载编译 repo

0x02 生成差异包
如果你刚刚编译成了bsdiff,在命令行里面输入bsdiff或者bspatch就会出现如下的信息:


其中bsdiff用于比较新旧文件的差异部分并生成差异包,bspatch根据之前差异包和旧文件生成新文件,我们可以从这两个可执行文件的报错信息看出该命令如何使用。我们这里有两个文件:new.so 和 old.so

之后我们运行 diff old.so new.so patch.so便生成了差异包patch.so

0x03 合成新版本
通过刚刚的介绍,我们已经在android端实现了相关的库,只需要简单的调用

YPatch.patch(oldFilePath, newFilePath, patchFilePatch)

便可以将新版本存放到newFilePath指定的目录下

结合Small框架

上面好像都是在讲原理,没有具体的实践讲解的话,估计读者还是不懂,我们现在就结合Small框架来看看如何做到增量更新。
对于我们的Small框架,我们要知道,它把每个插件都编译成.so文件,然后存放到app的native目录下,不过,如果它发现自己的download目录有新的插件,那么就会去加载download目录下的插件,并且这种加载优先权是最大的,也就是说它会优先加载download目录下的插件。所以,如果我们要做增量更新,旧文件就从app的native目录进行读取,然后从服务器端下载增量包,最后合成的文件存放到download目录下,这样每次插件启动都会到download目录下加载新的插件。

实现:

        //其中pluginUri对应的是bundle.json中插件对应的uri
        //下文有介绍
        String packageName = parsePackageName(context, pluginUri);
        if (TextUtils.isEmpty(packageName)) 
            Log.e(TAG, "can't parse plugin's package name, check if assets/bundle.json is deleted");
            return;
        

        // small框架的约定就是,插件名字是以lib+包名.so明明的
        // 比如如果我们插件的包名是com.chan.app.setting
        // 那么对于插件名就是libcom_chan_app_setting.so
        final String soName = "lib" + packageName.replaceAll("\\\\.", "_") + ".so";

        //找到旧版本的插件安装包
        final File oldPlugin = new File(context.getApplicationInfo().nativeLibraryDir, soName);
        //新版本都存放到small指定的download目录下
        final File newPlugin = new File(FileUtils.getDownloadBundlePath(), soName);

        //开始下载patch
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(uri).build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() 
            @Override
            public void onFailure(Request request, IOException e) 

            

            @Override
            public void onResponse(Response response) throws IOException 

                //保存从服务器端下载的增量包
                File patch = new File(FileUtils.getDownloadBundlePath(), "patch.so");
                FileOutputStream fileOutputStream = new FileOutputStream(patch);
                byte[] content = response.body().bytes();
                fileOutputStream.write(content);
                fileOutputStream.flush();
                fileOutputStream.close();

                //合成的新插件安装包存放文职有new Plugin指定
                YPatch.patch(oldPlugin.getAbsolutePath(), newPlugin.getAbsolutePath(), patch.getAbsolutePath());
            
        );

可以看到这个函数中出现的pluginUri,它其实对应的是bundle.json中插件的uri:


  "version": "1.0.0",
  "bundles": [
    
      "uri": "main",
      "pkg": "com.chan.app.main",
      "rules": 
        "item": ".ItemActivity"
      
    ,
    
      "uri": "setting",
      "pkg": "com.chan.app.setting",
      "rules": 
        "index": ".MainActivity"
      
    
  ]

也就是这里的main, setting

而这个bundle.json就是宿主中asset下的small配置文件:

示例代码:

OkSmall.merge(LaunchActivity.this, "setting", "http://192.168.1.100:8080/patch.so");
                Toast.makeText(LaunchActivity.this, "重启应用后更新生效", Toast.LENGTH_SHORT).show();

至此,所有的内容已经介绍完毕

要踩的坑

更新插件的时候要记得把插件的versionCode加大,比如 我们这里的setting插件:

修改它的build.gradle文件:


要记得加大11行的数值,不然加载还是不成功的

引用

  • Small框架
  • Android增量升级通用代码
  • 结合Small的增量升级方案

以上是关于Android Small框架增量升级方案的主要内容,如果未能解决你的问题,请参考以下文章

Android增量升级(结合small框架)

Android增量升级(结合small框架)

Android Small插件化框架源码分析

基于Small及Weex的定制化APP方案

基于Small及Weex的定制化APP方案

android黑科技系列——应用市场省流量更新(增量升级)原理解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/624242.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vscode下,camke构建QT项目成功后,Cmake/Launch无法出现程序窗口的原因和解决方式

由于可执行程序根目录下没有 qt 相关 dll 文件,直接运行会出现一闪而过的问题,所以需要进入 build目录,终端运行类似如下指令: D:\QT\5.15.2\mingw81_64\bin\windeployqt.exe .\test001.exe 注意:环境变量不能配置ms…

计算机视觉特征图可视化与注意力图可视化(持续更新)

1.YOLOv5 特征图可视化 可视化代码: def feature_visualization(x, module_type, stage, n2, save_dirPath(runs/detect/exp)):"""x: Features to be visualizedmodule_type: Module typestage: Module stage within mod…

前端工程化-NPM

前端工程化-NPM 1.什么是NPMNPM安装基本使用 1.什么是NPM NPM代表npmjs.org这个网站,这个站点存储了很多Node.js的第三方功能包。 NPM的全称是Node Package Manager,它是一个Node.js包管理和分发工具,已经成为非官方的…

DR模式 LVS负载均衡群集部署

DR模式 LVS负载均衡群集部署 一、LVS-DR工作原理1.数据包流向分析2.LVS-DR中的ARP问题3.LVS-DR模式的特点 二、LVS-DR部署1.部署NFS服务器2.配置2台节点服务器3.部署调度服务器 一、LVS-DR工作原理 1.数据包流向分析 (1)客户端发送请求到 Director Serv…

Spring Cloud Ribbon源码解析,Ribbon为什么可以实现负载均衡,为什么可以用服务名调用

文章目录 一、Ribbon概述1、Ribbon简单使用(1)引包(2)使用方式一:RestTemplateLoadBalanced(3)使用方式二:LoadBalancerClient 2、问题来了 二、前置知识回顾1、复习Qualifier的作用…

时序逻辑与组合逻辑

目录 一、概念 二、区别 一、概念 数字电路按照逻辑功能一般可以分为组合逻辑和时序逻辑。组合逻辑电路是指不含有任何存储器件(一般指寄存器)的电路,它的输出只和当前电路的输入有关;时序逻辑电路含有存储器件,可以…

[PyTorch][chapter 38][ResNet ]

前言: 论文地址: https://arxiv.org/pdf/1512.03385.pdf 残差网络是由来自Microsoft Research的4位学者提出的卷积神经网络,在2015年的ImageNet大规模视觉识别竞赛(ImageNet Large Scale Visual Recognition Challenge, ILSVRC&am…

[ATL/WTL]_[初级]_[如何获取ListView点击的单元格区域]

场景 在做Win32/WTL开发时,CListViewCtrl控件是常用的表格控件。有时候自绘listview时,需要在单元格上绘制小图标,并且小图标能响应鼠标点击的操作。 那么如何实现判断是否点击了小图标呢? 说明 要响应点击单元格上的小图标&…

MongoDB笔记

mongoDB基础知识 MongoDB的三个核心特性:灵活设计(No Schema)、高可用和分布式(可平行扩展),另外MongoDB自带数据压缩功能,使得同样的数据存储所需的资源更少。 No Schema(BJSON&a…

NeRF-Diffusion系列文章阅读

文章目录 前置知识《Latent-NeRF for Shape-Guided Generation of 3D Shapes and Textures》【CVPR23】《NeRDi: Single-View NeRF Synthesis with Language-Guided Diffusion as General Image Priors》【CVPR23】《SparseFusion: Distilling View-conditioned Diffusion for …

【系统找不到D盘指定驱动设备之解决方法】

文章目录 1.原因2.解决经过3.最终解决办法 1.原因 今天在搞课设,突然之间电脑一顿卡,然后整个电脑屏幕空白,D盘以及所有的安装软件都不见了。点击屏幕出现提示系统找不到指定驱动设备等等提示,查看此电脑发现D盘神奇的消失了。 …

Kafka面试题01

1、kafka有哪些特点 高吞吐,低延迟 可以热扩展 并发度高 具有容错性(即使挂的只剩下一台也可以正常工作) 可靠性高2、请简述你在那些场景下会选择kafka?kafka的应用 日志收集: 一个公司可以用kafka收集各种服务的log…

B站、抖音上那些4K、60帧视频是如何修复的?

如何把一个不清晰的视频变成高清的视频?今天就来教大家视频画质修复把720p的渣画质变成4K超清画质。 相信对于电影和后期爱好者来说,糊成马赛克的画质一定劝退了无数人,那不妨试试这个 牛学长视频修复工具 牛学长视频修复工具通过高级的AI…

Java网络开发(Tomcat)—— 登陆 和 注册功能 的实现 从html 到 jsp 迭代升级 session保存登陆信息

目录 引出登陆功能---从html到jsp1.登陆--用post请求2.用html文件的form表单登陆(1)index.html页面(2)login.html登陆的页面(3)LoginServlet.java处理输入信息的代码(4)登陆成功&…

ChatGPT提示大解析:如何有效定制Prompt并用插件管理

有时候,你可能在编程时遇到难题,需要解决方法。有时候,你在学习新的语言时,想要找到一位悉心的教师。又或者,你可能只是需要一些新的灵感,来润色你的文章。在所有这些情况下,ChatGPT都可以发挥巨…

轻量应用服务器哪款性价比高?

最近云服务器618活动正在火热进行中,选对时间入手自己心仪的云服务器其实可以为你省去一大笔费用,这里先开门见山将三家的云服务器活动粒度做个对比。 腾讯云 懂行的人一看这种配置性价比就会内心无比激动,按照平时的价格根本买不到这么实惠的…

JavaSE基础知识笔记

​1、基础语法 在一个Java源文件中可以声明多个class,但是最多只有一个类可以被声名为public,而且被声名为public的类的类名必须与源文件名相同。 计算机底层都以补码的方式来存储数据!目的是为了简化计算机的结构设计,同时提升运…

如何在Moonbeam设置多重签名钱包,加固资产安全

Moonbeam Safe是以太坊上Safe(先前名为Gnosis Safe)的分叉。Safe于2018年正式推出,并发展成为了以太坊上知名的去中心化托管协议和集体资产管理平台。 Moonbeam Safe可用于创建多重签名Safe钱包,通过配置一个多签(mul…

02.Web大前端时代之:HTML5+CSS3入门系列~H5结构元素

Web大前端时代之&#xff1a;HTML5CSS3入门系列&#xff1a;Web大前端时代之&#xff1a;HTML5CSS3入门系列 - 毒逆天 - 博客园 1.结构元素 可以理解为语义话标记&#xff0c;比如&#xff1a;以前这么写<div id"nav"></div> 现在偷懒写&#xff1a;&l…

JavaWeb笔记_SpringBoot原理

JavaWeb笔记_SpringBoot原理 配置优先级Bean管理获取BeanBean作用域第三方Bean SpringBoot原理自动配置原理ComponentScan组件扫描Import导入源码跟踪Conditional自定义starter创建aliyun-oss-spring-boot-starter模块创建aliyun-oss-spring-boot-autoconfigure 来源 配置优先级…