网上AssetsManagerEx 实现热更新的同类教程很多,这里我就不详细介绍了,基本上按照cocos2d-x的demo来做就行了,但有几个坑要个大家提醒一下.
1.AssetsManagerEx的创建,第一个参数是当前的project.manifest文件路径,第二个是资源下载后的存放路径.更新后会下载的project.manifest与version.manifest文件放到 存放路径 !!!而且名字也是叫project.manifest与version.manifest,所以不建议改成其他的名字,给自己带来麻烦.具体路径可根据自己的项目配置进行修改
const auto fileUtils = FileUtils::getInstance();
const auto writablePath = fileUtils->getWritablePath();
if (fileUtils->isFileExist(writablePath + "Assets/project.manifest"))
{
_AssetsManagerEx = AssetsManagerEx::create(writablePath + "Assets/project.manifest", writablePath + "Assets/");
}
else
{
_AssetsManagerEx = AssetsManagerEx::create("project.manifest", writablePath + "Assets/");
}
_AssetsManagerEx->retain();
2.更新进度
// 获得当前下载文件的下载百分比
int percent = event->getPercent();
// 获得总的下载百分比
int percentByFile = event->getPercentByFile();
以上两个只是小坑,AssetsManagerEx现在是对比单个文件来下载,所以如果不对多个文件进行压缩,肯定会使第一次更新或跨N多个版本需要一次性下载大量的文件,比如我当前这个项目总共有2000多个,生成的json文件有7000多行.这时候你就会发现log中打印了 Can't open file:XXXX的信息.这是因为AssetsManagerEx会在一开始将所有需要下载的东西加入下载队列,而下载会为下载的文件创建一个.temp的文件,并且一直保持的打开,而同时打开的文件是有上限的,并且不同的操作系统上限也不同,比如windows是512个,所以我对源代码多处进行了修改,当打开到达上限之后,不在继续添加,而是下载完成前面一批之后再加入一批.
CCDownloader-curl.cpp 143 行
函数 bool init(const string& filename, const string& tempSuffix)
// open file
_fp = fopen(util->getSuitableFOpen(_tempFileName).c_str(), "ab");
if (nullptr == _fp)
{
_errCode = DownloadTask::ERROR_FILE_OP_FAILED;
_errCodeInternal = 0;
_errDescription = "Can't open file:";
_errDescription.append(_tempFileName);
break;// 增加break 让init返回false
}
ret = true;
只增加了break;让打开失败返回false;
CCDownloader-curl.cpp 745行
函数 IDownloadTask *DownloaderCURL::createCoTask(std::shared_ptr<const DownloadTask>& task)
// 增加对返回值的判断
if (!coTask->init(task->storagePath, _impl->hints.tempFileNameSuffix))
{
// 失败释放并返回空
delete coTask;
return nullptr;
}
本来是没有判断的 现在加上判断释放并返回nullptr
CCDownloader.cpp 174行
//task_->_coTask.reset(_impl->createCoTask(task));
// 创建下载任务
IDownloadTask* tempTask = _impl->createCoTask(task);
if (tempTask)
{
task_->_coTask.reset(tempTask);
}
else
{
return nullptr;
}
由于现在回返回nullptr,所以对返回值进行判断如果有还是和以前一样,没有返回nullptr
AssetsManagerEx.h 193行
void batchDownload();
// 加入下一批
void batchDownloadAgain();
//! The event of the current AssetsManagerEx in event dispatcher
std::string _eventName;
通过调用batchDownloadAgain来下载下一批资源
AssetsManagerEx.h 243行
// 当前下载到哪
DownloadUnits::iterator _downloadIter;
// 再次开启下载需要到达的数量
int _downloadAgainNum;
增加两个成员变量记录下载状态
AssetsManagerEx.cpp 946行
// Reduce count only when unit found in _downloadUnits
_totalWaitToDownload--;
_percentByFile = 100 * (float)(_totalToDownload - _totalWaitToDownload) / _totalToDownload;
// 下载下一批
if (_totalToDownload - _totalWaitToDownload >= _downloadAgainNum)
{
batchDownloadAgain();
}
// Notify progression event
dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "");
通过判断当前已经下载了的数量来确定是否要加入下一批
AssetsManagerEx.cpp 992行
函数 void AssetsManagerEx::batchDownload() 修改
void AssetsManagerEx::batchDownload()
{
// 开始下载前初始化下载位置
_downloadIter = _downloadUnits.begin();
_downloadAgainNum = 0;
batchDownloadAgain();
}
现在这个方法用来初始化 并开启一次下载
AssetsManagerEx.cpp 1006行
void AssetsManagerEx::batchDownloadAgain()
{
for (; _downloadIter != _downloadUnits.end(); ++_downloadIter)
{
++_downloadAgainNum;
DownloadUnit& unit = _downloadIter->second;
// 判断下载任务创建是否失败
if (_downloader->createDownloadFileTask(unit.srcUrl, unit.storagePath, unit.customId) == nullptr)
{
--_downloadAgainNum;
// fopen打开文件有限制 创建任务失败
break;
}
}
}
增加对batchDownloadAgain的实现
C++实现的委托,如果有兴趣的话可以一起讨论一下哈
https://git.oschina.net/.cgy.com/Delegate