android包名更换后升级方案,Android增量升级方案

背景

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

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

引用

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

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

相关文章

Linux 学习 Ubuntu 12.04 配置指南

关于Ubuntu 就不在此详细的叙述, 安装方法: 硬盘安装,速度效果都还不错 http://www.nenew.net/ubuntu-12-04-hard-disk-install-tutorial.html 详细的方法可以去这里看一下 U盘安装:这个就更加的简单,我一般都是使用 U…

vue created 生命周期

在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el属性目前不可见。 methods、data、watch等可以…

android cne服务,Android内存优化-了解内存篇

查看系统内存文件shellaries:/ $ cat /proc/meminfoMemTotal: 1970216 kBMemFree: 83756 kBBuffers: 156020 kBCached: 702516 kBSwapCached: 0 kBActive: 1160284 kBInactive: 397932 kBActive(anon): 778932 kBInactive(anon): 2228 kBActive(file): 381352 kBInactive(file)…

《鸟哥的linux私房菜-服务器篇 第三版》 RHCA亲授

经典再现,《鸟哥的linux私房菜-服务 器篇(第三版)》远程班隆重推出! 鸟哥的linux的私房菜是linux教材中的 经典中的经典!是学习linux的绝佳资 料! 上课时间: 周一到周五 上课方式:全…

装饰者模式

装饰者模式的实现有两个要求:1.装饰者类与目标类要实现相同的借口,或者继承自相同的抽象类。2.装饰者类中要有目标类的引用作为成员变量,具体的赋值一般通过带参构造器完成。 按着这两个要求我们进行类的编写。 目标类: //接口 pa…

子弹类

import pygame # pygame2d游戏 import time from pygame.locals import *class HeroPlane(object):def __init__(self,screen_temp):self.x210self.y700self.screenscreen_tempself.image pygame.image.load("./feiji/hero1.png")self.bullet_list[]def display(sel…

Shell中的特殊字符

通配符 当需要用命令处理一组文件,例如file1.txt、file2.txt、file3.txt……,用 户不必一一输入文件名,可以使用Shell通配符。Shell命令的通配符含义如下表 引号 在 Shell 中引号分为 2 种:单引号、双引号。 ( 1 &…

树莓派换源、vim更新:树莓派更换国内可用镜像源

参考:树莓派vim更新:树莓派更换国内可用镜像源 作者:丶PURSUING 发布时间:2021-02-01 22:40:48 网址:https://blog.csdn.net/weixin_44742824/article/details/113530423?spm1001.2014.3001.5502 Ubuntu18.04换源更新…

android的帧布局,七、Android帧布局FrameLayout和霓虹灯效果

帧布局容器为每个加入其中的组件创建一个空白的区域(称为一帧),所有每个子组件占据一帧,这些帧都会根据gravity属性执行自动对齐。FrameLayout的常用XML属性和相关方法XML属性相关方法说  明android:foregroundsetForeground(Drawable)设置该帧布局容器…

flutter能开发游戏吗_Steam上架游戏开发软件,不用代码也能制作游戏,而且还是免费的...

时代在变化,科技在进步,曾几何时我们一度以为的高科技,在现在看来也不过是平常到不能再平常的东西。游戏开发也一样,以前需要代码才能开发制作而成,现如今都不需要了,直接编辑就OK,Steam商城这次…

Flask之flask-session

简介 flask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存,该组件则将支持session保存到多个地方,如: redis:保存数据的一种工具,五大类型。非关系型数据库memcachedfilesy…

快速构建Windows 8风格应用10-设备方向

本篇博文主要介绍常用支持Windows 8操作系统设备的方向、如何获取当前设备方向、DisplayProperties类 常用支持Windows 8操作系统设备的方向在我们常用的设备当中,Windows 8是通过什么来监控设备方向呢?答案是方向传感器,那么对于设备的不同方…

android viewpager fragment传值,Android开发中如何解决Fragment +Viewpager滑动页面重复加载的问题...

前言之前在做一个Viewpager上面加载多个Fragment时总会实例化已经创建好的Fragmnet对象类似viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {Overridepublic Fragment getItem(int position) {switch(position){case 0:fragmentsnew Fragmnet01(…

CSDN怎么转载别人的博客

参考:CSDN怎么转载别人的博客 作者:zhongjianblackberry 发布时间:2018-03-06 11:57:59 网址:https://blog.csdn.net/zhongjianblackberry/article/details/79456338 目录转载CSDN博客步骤:Markdown和HTML相关小知识Ma…

青岛西海岸惠普大数据_青岛西海岸新区用好卫星大数据 为城市治理全面赋能...

来源:环球网为推进城市治理数字化程度,提升城市治理的智能化和精细化水平,青岛西海岸新区搭建了人工智能搜索视觉分析平台,以月度更新的频率,汇聚了新区0.5米高分辨率卫星影像数据,通过数据资源共享系统为各…

总结jenkins Android自动打包遇到的坑

一、ndk-build报错 [roothejianlai-jenkins LearnGradle]# ndk-build /usr/local/android-ndk-r8/ndk-build: /usr/local/android-ndk-r8/prebuilt/linux-x86/bin/make: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory 解决方法:安装glibc.i6…

微博VS微信,谁更有移动优势

微博、微信,一个是中国互联网的明星,一个是中国互联网的后起之秀,前者出身于中国最大的门户网站新浪,后者出身于中国最大的即时通讯公司腾讯。作为各自公司在移动互联网上的主推产品,两者都背负着公司的巨大期望。那么…

android的热修复,Android热修复原理

热修复框架技术主要有三类,代码修复,资源修复,动态链接库修复。资源修复很多资源修复的框架参考了Instant Run资源修复的原理,所以先了解一下Instant RunInstant RunInstant Run是Android Studio 2.0以后新增的一个运行机制&#…

树莓派的四种登陆方式

参考:树莓派的4种登陆方式 作者:丶PURSUING 发布时间:2021-02-02 09:15:30 网址:https://blog.csdn.net/weixin_44742824/article/details/113524929?spm1001.2014.3001.5502 目录一、HDMI视频线二、串口1.修改sd卡中的系统文件2…

丰收互联蓝牙key怎么开机_ublox收购Rigado的蓝牙模块业务,扩大蓝牙低功耗产品组合...

全球领先的定位与无线通讯技术供应商u-blox 宣布,已与 Rigado签署资产购买协议,收购其蓝牙模块业务。Rigado是商业物联网Edge-as-a-Service(EaaS)边缘即服务网关解决方案的领先供应商,于2015年开始提供通过认证的无线模块。强化蓝牙产品系列此…