热更新压缩包

问题1:
我已经根据官网教程执行了一遍文件的热更新,若我想把所有的热更新文件压缩成一个zip,那热更新的时候,还需要设置并发下载数吗?是不是只会有一个线程去下载这个热更包?

问题2:
下载时,我可以获得下载的字节数,和总数,那解压时怎么获取解压的进度?

zip 你是通过downloader来下载的吗?

不是,我还没试过热更压缩包,我是根据官网项目,通过assetManager热更的文件,想要改成热更压缩包。

直接下载压缩包,跟之前的,然后本地解压覆盖你的热更目录

cc.assetManager.loadRemote(url, {
            ext: ".bin",
            onFileProgress: (current, total) => {
                this.current = current;
                this.total = total;
                this.loadSprite.fillRange = this.current / this.total;
            }
        }, (err, bufferAsset) => {
            let data = bufferAsset._buffer;
            let dirpath = jsb.fileUtils.getWritablePath() + 'zips/';
            let filepath = dirpath + "hotpack.zip";
            if (!jsb.fileUtils.isDirectoryExist(dirpath)) {
                jsb.fileUtils.createDirectory(dirpath);
            } if (jsb.fileUtils.writeDataToFile(new Uint8Array(data), filepath)) {
                //解压压缩包
                //解压完之后设置热更路径并且重启
            }
        })

image
修改一下这个java文件,不然会导致下载超时

public static Cocos2dxDownloader createDownloader(int id, int timeoutInSeconds, String tempFileSuffix, int maxProcessingTasks) {
        Cocos2dxDownloader downloader = new Cocos2dxDownloader();
        downloader._id = id;

        if (timeoutInSeconds > 0) {
            downloader._httpClient = new OkHttpClient().newBuilder()
                    .followRedirects(true)
                    .followSslRedirects(true)
                    .connectTimeout(timeoutInSeconds, TimeUnit.SECONDS)
                    .writeTimeout(timeoutInSeconds, TimeUnit.SECONDS)
                    .readTimeout(timeoutInSeconds, TimeUnit.SECONDS)
                    .build();
        } else {
            downloader._httpClient = new OkHttpClient().newBuilder()
                    .followRedirects(true)
                    .followSslRedirects(true)
                    .build();
        }


        downloader._tempFileNameSuffix = tempFileSuffix;
        downloader._countOfMaxProcessingTasks = maxProcessingTasks;
        return downloader;
    }

复制我的替换就行了

2赞

大佬解压怎么操作的, 每次热更都是下载整个zip进行更新吗

关于解压进度,安卓可以使用zip4j,这个开源解压代码。在github上面有,可以获取到解压进度,同时支持更多解压格式,并且可以附带解压带密码的压缩包。通过java回调js去同步压缩进度。不过要注意,解压的时候放在UI线程解压,不然会卡住整个游戏画面

public static void unZipPackDemo(final String inputString, final String outputString, final String passWord) {
        Cocos2dxHelper.getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    String localPath = m_activity.getFilesDir().getAbsolutePath();
                    String example_inputString = "/zips/BPcak.zip";
                    String example_outputString = "/blackjack-remote-asset";
                    Zip4jUtils.unZip(localPath + "/" + inputString, localPath + outputString, passWord);
                } catch (Exception e) {
                    Log.e(TAG, "ZipUtilsErr: ", e);
                    return;
                }
            }
        });
    }

这个方案,是另一种新方法吗?和官网上的热更新方案不太一样。官网上是用jsb.assetManager,下载都是内部封装好,不需要我去loadRemote。哪种会好点?

都一样,只不过2种方式侧重点不一样。
官方的方案是本地对比服务器的差异文件,不过前提是你每次更新都得把打包好的资源全部上传服务器,如果更新过于过于太多的时候,速度肯定比不上压缩包,同时浪费的流量也比压缩包多,好处就是省事,懒人模式开启。

压缩包方案就是在本地对比好差异文件,然后将差异文件打成一个压缩包,客户端只需无脑的下载最新的压缩包,然后解压就完事了。

网络越垃圾的的地方压缩包方案更吃香,但是你得自己支持断点续传

好的,非常感谢你的解答,我想要结合一下这两个方面,写一个程序来生成差异压缩包,然后用官网的方式去热更这个压缩包,就是不知道能不能成功,也不知道怎么获取解压的进度。

我看到一些文章上说,官网的热更方法,跟新压缩包后会自动解压,所以我不知道是不是真的,也不知道怎么获取压缩的进度,所以发个帖子询问一下。

你给了我另一个方案,如果方案一走不通,我就可以用你这个方案。

你这样不行的,你还没有理解官方的热更方式。
官方的热更是这样的 apk携带一个mainfest文件 远程服务器携带一个mainfest文件。客户端需要热更的时候将服务器的mainfest文件下载下来,然后对比本地的mainfest文件,根据md5码差异提取出需要下载资源的url地址。然后一个一个去下载,下载完之后将本地的mainfest文件替换为服务器的mainfest文件。

压缩包热更是在这样的。 本地构建之后,通过工具对比。提取出有差异的文件,保留这些文件的相对路径,然后将这些文件压缩成压缩包上传至服务器。客户端只需无脑的下载这1个压缩包,然后解压就可以了。

我想先试试,主要看官方的能不能直接热更压缩包解压,不行的话,那就用你教我的方法用原生封装一下。

我不理解你说的官方这个词。
如果官方指cocos这个软件,可以
如果官方指 jsb.AssetsManager + 压缩包,不可以

太关键了,,赶紧mark。。

目前ccc的传统热更是差异下载的,不管跨越多少版本,通过mainfest md5 比较只下载差异文件。按楼主的说法,有两种方式:1 压缩最新包的所有文件,对所有需要更新的客户端做覆盖更新,这样每次下载的体积会很大(虽然只有一次请求)。2: 需要保存所有历史版本包体,新包对每个历史版本生成差异的zip压缩文件,然后客户端通过版本请求对应差异 zip包,这样只请求一次且包体也小,但是维护难度随版本增多增加。所以还是传统的热更简单明了。

1、官方热更zip可自动解压的,看源码就行。
2、mainfest对比差异只需保证结果只有一个zip差异以及新版本删除的文件即可。(也就是解压后和官网方案结果一样)
3、解决历史版本过多可动态可配zip热更版本数量,超出的都走官网方案。实在太久远的可考虑直接让玩家下载最新包
4、方案2的改法对引擎层面0侵入(因为我懒,走的全部是官方标准流程,稳定性高)

有谁看明白第二种方案的规则了吗 给说说?
本地对比好差异文件? 怎么对比? 可能已经有100多个版本了 那么要完成每个版本到最新版本的对比差异,然后再打成包? 这个工作夸张到没边了都
如果说官方原始的方案流量会大 但官方原始的方案也可以用压缩方式的 为什么会导致流量大? 官方原始的方案既可以用压缩 也不用管中间的任何版本 非常合理到位的 管理起来也很方便 没觉得有什么问题的

一般只提供20个差异版本上限,由脚本完成对比上传服务器,超过20个版本那就提示玩家重新下载APP。因为你20个压缩包的流量极有可能超过下载整个APP的流量和时间了,所以干脆重新下载最新的APP。

常用用户一般都是紧跟着版本更新的,不会超过3个版本。如果超过了3个版本,大部分都是僵尸用户,不用考虑他们了。

第一点可以具体说说吗,官方热更自动解压

20个差异?
不要说维护20个版本的差异,维护2个版本的差异 我觉得都是个烦人容易出错的工作,
典型的自己给自己找麻烦的事情,
为什么不是总是面对最终最新的版本呢 就一个版本 维护起来多简单 多容易,
所以你说的方案比官方的只面对维护最新的版本的方式 已经差了一个数量级了 甚至几个数量级,因为你要照顾之前的版本还
然后流量问题 官方方案支持压缩方式也 你的这种方案 也没有体现出流量优势,
如果让我说 你的方案和官方的比 没有任何优势,还有劣势,因为你多了一个要维护多个版本相互差异的工作,
这个是所有运营和开发人员最忌讳的工作算是

官方已经说的很清楚了 不是吗。

Manifest 格式

Manifest 格式是我们用来比较本地和远程资源差异的一种 json 格式,其中保存了主版本信息、引擎版本信息、资源列表及资源信息等:

{
    "packageUrl" :          远程资源的本地缓存根路径
    "remoteVersionUrl" :    [可选项] 远程版本文件的路径,用来判断服务器端是否有新版本的资源
    "remoteManifestUrl" :   远程资源 Manifest 文件的路径,包含版本信息以及所有资源信息
    "version" :             资源的版本
    "engineVersion" :       引擎版本
    "assets" :              所有资源列表
        "key" :             资源的相对路径(相对于资源根目录)
        "md5" :             md5 值代表资源文件的版本信息
        **"compressed" :      [可选项] 如果值为 true,文件被下载后会自动被解压,目前仅支持 zip 压缩格式**
        "size" :            [可选项] 文件的字节尺寸,用于快速获取进度信息
    "searchPaths" :         需要添加到 FileUtils 中的搜索路径列表
}