Cocos2dx热更新遇到的那些坑

1、Cocos2dx热更新因为文件名含有空格,ios下载失败bug修改

问题描述:

  项目中偶尔遇到美术图片命名时不规范,导致图片名字含有空格。导致ios热更新时,遇到下载失败。

解决方案:

1.从新改名字(以后命名一定要规范)

2.空格转义 解决下载失败问题

url

web 开发中通过问号(?)方式在浏览器地址栏中传值时。浏览器是通过“&”来区分问号后的参数个数的。 如果出现传值参数中带有“&”时,在接受页面就会出现错误,类似如下请求路径:/next.jsp?param1=hendhs89&furej & param2=sss
参数param1中含有转义字符“&” ,这样会导致被请求页的参数接收错误。
在传值前 通过 java.net.URLEncoder.encode(param1) 编码处理后,可将转义字符转为16进制;
1. + URL 中+号表示空格 %2B
2. 空格 URL中的空格可以用+号或者编码 %20
3. / 分隔目录和子目录 %2F
4. ? 分隔实际的 URL 和参数 %3F
5. % 指定特殊字符 %25
6. # 表示书签 %23
7. & URL中指定的参数间的 分隔符%26
8. = URL中指定参数的值 %3D
9. ! URL中指定参数的值 %2
 

具体解决方案

1、AssetsManagerEx::startUpdate()中,拼接地址时,将空格转义

void AssetsManagerEx::startUpdate()
{
    if (_updateState != State::NEED_UPDATE)
        return;

    _updateState = State::UPDATING;
    // Clean up before update
    _failedUnits.clear();
    _downloadUnits.clear();
    _compressedFiles.clear();
    _totalWaitToDownload = _totalToDownload = 0;
    _percent = _percentByFile = _sizeCollected = _totalSize = 0;
    _downloadedSize.clear();
    _totalEnabled = false;
    
    // Temporary manifest exists, resuming previous download
    if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest))
    {
        _tempManifest->genResumeAssetsList(&_downloadUnits);
        _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();
        this->batchDownload();
        
        std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload);
        dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
    }
    // Check difference
    else
    {
        // Temporary manifest not exists or out of date,
        // it will be used to register the download states of each asset,
        // in this case, it equals remote manifest.
        _tempManifest->release();
        _tempManifest = _remoteManifest;
        
        std::unordered_map<std::string, Manifest::AssetDiff> diff_map = _localManifest->genDiff(_remoteManifest);
        if (diff_map.size() == 0)
        {
            updateSucceed();
        }
        else
        {
            // Generate download units for all assets that need to be updated or added
            std::string packageUrl = _remoteManifest->getPackageUrl();
            for (auto it = diff_map.begin(); it != diff_map.end(); ++it)
            {
                Manifest::AssetDiff diff = it->second;

                if (diff.type == Manifest::DiffType::DELETED)
                {
                    _fileUtils->removeFile(_storagePath + diff.asset.path);
                }
                else
                {
                    std::string path = diff.asset.path;
                    // Create path
                    _fileUtils->createDirectory(basename(_storagePath + path));

                    DownloadUnit unit;
                    unit.customId = it->first;
                    
                    std::string str(path),s2(" "),s3("%20");
                    std::string::size_type pos=0;
                    std::string::size_type a=s2.size();
                    std::string::size_type b=s3.size();
                    while((pos=str.find(s2,pos))!=std::string::npos)
                    {
                        str.replace(pos,a,s3);
                        pos+=b;
                    }
                    unit.srcUrl = packageUrl + str;
                    unit.storagePath = _storagePath + path;
                    _downloadUnits.emplace(unit.customId, unit);
                }
            }
            // Set other assets' downloadState to SUCCESSED
            auto &assets = _remoteManifest->getAssets();
            for (auto it = assets.cbegin(); it != assets.cend(); ++it)
            {
                const std::string &key = it->first;
                auto diffIt = diff_map.find(key);
                if (diffIt == diff_map.end())
                {
                    _tempManifest->setAssetDownloadState(key, Manifest::DownloadState::SUCCESSED);
                }
            }
            _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();
            this->batchDownload();
            
            std::string msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload);
            dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
        }
    }
}

2、Manifest.cpp

void Manifest::genResumeAssetsList(DownloadUnits *units) const
{
    for (auto it = _assets.begin(); it != _assets.end(); ++it)
    {
        Asset asset = it->second;
        
        if (asset.downloadState != DownloadState::SUCCESSED)
        {
            DownloadUnit unit;
            unit.customId = it->first;
            std::string str(asset.path),s2(" "),s3("%20");
            std::string::size_type pos=0;
            std::string::size_type a=s2.size();
            std::string::size_type b=s3.size();
            while((pos=str.find(s2,pos))!=std::string::npos)
            {
                str.replace(pos,a,s3);
                pos+=b;
            }
            unit.srcUrl = _packageUrl + str;
            unit.storagePath = _manifestRoot + asset.path;
            units->emplace(unit.customId, unit);
        }
    }
}

2、Cocos2dx热更新因为文件名含有空格,ios下载失败bug修改

问题描述:

AsstsManagerEx: project.manifest may be downloaded twice。

project.manifest下载两次 ,导致热更新失败。打印log提示 解析project.manifest失败。

解决方案:

Cocos 3.14版本 自己解决了这个问题,根据就该日志 更新下载器。

 

3、更新过程强制退出,导致不能缓存下载。下载失败之后,不对比MD5所有文件都下载bug。

新版本不知道有没有。这个对应版本是 3.11

解决思路 。

下载器一开始先判断有没有缓存文件,有缓存文件的话,直接读取缓存文件。由于上一次强退没有及时将下载进度写到缓存文件中

所以所有文件的状态都是1.这里由于是临时清单文件,没有做MD5对比。所有所有文件都被添加到下载清单,出现bug

如果正常出错,没有强退。下载器会正常调用,写临时清单,这个不会有bug。

 
   
void AssetsManagerEx::startUpdate()
{
    if (_updateState != State::NEED_UPDATE)
        return;

    _updateState = State::UPDATING;
    // Clean up before update
    _failedUnits.clear();
    _downloadUnits.clear();
    _compressedFiles.clear();
    _totalWaitToDownload = _totalToDownload = 0;
    _percent = _percentByFile = _sizeCollected = _totalSize = 0;
    _downloadedSize.clear();
    _totalEnabled = false;
    
    // Temporary manifest exists, resuming previous download
    if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest))
    {
        std::unordered_map<std::string, Manifest::AssetDiff> diff_map = _localManifest->genDiff(_remoteManifest);
        if (diff_map.size() == 0)
        {
            updateSucceed();
        }
        else
        {
            // Set other assets' downloadState to SUCCESSED
            auto &assets = _remoteManifest->getAssets();
            for (auto it = assets.cbegin(); it != assets.cend(); ++it)
            {
                const std::string &key = it->first;
                auto diffIt = diff_map.find(key);
                if (diffIt == diff_map.end())
                {
                    _tempManifest->setAssetDownloadState(key, Manifest::DownloadState::SUCCESSED);
                }
            }
            _tempManifest->genResumeAssetsList(&_downloadUnits);
            _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();
            this->batchDownload();
            
            std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload);
            dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
        }
    }
    // Check difference
    else
 
   

 

 

 

遇到问题不要着急,一步一步确定问题。经常看官网的coco动态,新版本的发布,以及bug的修改、

Cocos2dx git

Cocos2dx 官网

 

转载于:https://www.cnblogs.com/zhangfeitao/p/6489345.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值