mirror of https://github.com/axmolengine/axmol.git
Merge pull request #2567 from minggo/AssetsManager-asynchronization
Make AssetsManager download resources in a new thread
This commit is contained in:
commit
1a947ce1cd
|
@ -49,34 +49,49 @@ NS_CC_EXT_BEGIN;
|
||||||
#define BUFFER_SIZE 8192
|
#define BUFFER_SIZE 8192
|
||||||
#define MAX_FILENAME 512
|
#define MAX_FILENAME 512
|
||||||
|
|
||||||
AssetsManager::AssetsManager()
|
// Message type
|
||||||
: _packageUrl("")
|
#define ASSETSMANAGER_MESSAGE_UPDATE_SUCCEED 0
|
||||||
, _versionFileUrl("")
|
#define ASSETSMANAGER_MESSAGE_RECORD_DOWNLOADED_VERSION 1
|
||||||
, _version("")
|
#define ASSETSMANAGER_MESSAGE_PROGRESS 2
|
||||||
, _curl(NULL)
|
#define ASSETSMANAGER_MESSAGE_ERROR 3
|
||||||
|
|
||||||
|
// Some data struct for sending messages
|
||||||
|
|
||||||
|
struct ErrorMessage
|
||||||
|
{
|
||||||
|
AssetsManager::ErrorCode code;
|
||||||
|
AssetsManager* manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProgressMessage
|
||||||
|
{
|
||||||
|
int percent;
|
||||||
|
AssetsManager* manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of AssetsManager
|
||||||
|
|
||||||
|
AssetsManager::AssetsManager(const char* packageUrl/* =NULL */, const char* versionFileUrl/* =NULL */, const char* storagePath/* =NULL */)
|
||||||
|
: _storagePath(storagePath)
|
||||||
|
, _version("")
|
||||||
|
, _packageUrl(packageUrl)
|
||||||
|
, _versionFileUrl(versionFileUrl)
|
||||||
|
, _downloadedVersion("")
|
||||||
|
, _curl(NULL)
|
||||||
|
, _tid(0)
|
||||||
|
, _connectionTimeout(0)
|
||||||
|
, _delegate(NULL)
|
||||||
{
|
{
|
||||||
_storagePath = CCFileUtils::sharedFileUtils()->getWritablePath();
|
|
||||||
checkStoragePath();
|
checkStoragePath();
|
||||||
|
_schedule = new Helper();
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetsManager::AssetsManager(const char* packageUrl, const char* versionFileUrl)
|
AssetsManager::~AssetsManager()
|
||||||
: _packageUrl(packageUrl)
|
|
||||||
, _version("")
|
|
||||||
, _versionFileUrl(versionFileUrl)
|
|
||||||
, _curl(NULL)
|
|
||||||
{
|
{
|
||||||
_storagePath = CCFileUtils::sharedFileUtils()->getWritablePath();
|
if (_schedule)
|
||||||
checkStoragePath();
|
{
|
||||||
}
|
_schedule->release();
|
||||||
|
}
|
||||||
AssetsManager::AssetsManager(const char* packageUrl, const char* versionFileUrl, const char* storagePath)
|
|
||||||
: _packageUrl(packageUrl)
|
|
||||||
, _version("")
|
|
||||||
, _versionFileUrl(versionFileUrl)
|
|
||||||
, _storagePath(storagePath)
|
|
||||||
, _curl(NULL)
|
|
||||||
{
|
|
||||||
checkStoragePath();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetsManager::checkStoragePath()
|
void AssetsManager::checkStoragePath()
|
||||||
|
@ -114,10 +129,12 @@ bool AssetsManager::checkUpdate()
|
||||||
curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, getVersionCode);
|
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, getVersionCode);
|
||||||
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &_version);
|
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &_version);
|
||||||
|
if (_connectionTimeout) curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, _connectionTimeout);
|
||||||
res = curl_easy_perform(_curl);
|
res = curl_easy_perform(_curl);
|
||||||
|
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
{
|
{
|
||||||
|
sendErrorMessage(kNetwork);
|
||||||
CCLOG("can not get version file content, error code is %d", res);
|
CCLOG("can not get version file content, error code is %d", res);
|
||||||
curl_easy_cleanup(_curl);
|
curl_easy_cleanup(_curl);
|
||||||
return false;
|
return false;
|
||||||
|
@ -126,6 +143,7 @@ bool AssetsManager::checkUpdate()
|
||||||
string recordedVersion = CCUserDefault::sharedUserDefault()->getStringForKey(KEY_OF_VERSION);
|
string recordedVersion = CCUserDefault::sharedUserDefault()->getStringForKey(KEY_OF_VERSION);
|
||||||
if (recordedVersion == _version)
|
if (recordedVersion == _version)
|
||||||
{
|
{
|
||||||
|
sendErrorMessage(kNoNewVersion);
|
||||||
CCLOG("there is not new version");
|
CCLOG("there is not new version");
|
||||||
// Set resource search path.
|
// Set resource search path.
|
||||||
setSearchPath();
|
setSearchPath();
|
||||||
|
@ -137,8 +155,46 @@ bool AssetsManager::checkUpdate()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* assetsManagerDownloadAndUncompress(void *data)
|
||||||
|
{
|
||||||
|
AssetsManager* self = (AssetsManager*)data;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (self->_downloadedVersion != self->_version)
|
||||||
|
{
|
||||||
|
if (! self->downLoad()) break;
|
||||||
|
|
||||||
|
// Record downloaded version.
|
||||||
|
AssetsManager::Message *msg1 = new AssetsManager::Message();
|
||||||
|
msg1->what = ASSETSMANAGER_MESSAGE_RECORD_DOWNLOADED_VERSION;
|
||||||
|
msg1->obj = self;
|
||||||
|
self->_schedule->sendMessage(msg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncompress zip file.
|
||||||
|
if (! self->uncompress())
|
||||||
|
{
|
||||||
|
self->sendErrorMessage(AssetsManager::kUncompress);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record updated version and remove downloaded zip file
|
||||||
|
AssetsManager::Message *msg2 = new AssetsManager::Message();
|
||||||
|
msg2->what = ASSETSMANAGER_MESSAGE_UPDATE_SUCCEED;
|
||||||
|
msg2->obj = self;
|
||||||
|
self->_schedule->sendMessage(msg2);
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
self->_tid = 0;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void AssetsManager::update()
|
void AssetsManager::update()
|
||||||
{
|
{
|
||||||
|
if (_tid) return;
|
||||||
|
|
||||||
// 1. Urls of package and version should be valid;
|
// 1. Urls of package and version should be valid;
|
||||||
// 2. Package should be a zip file.
|
// 2. Package should be a zip file.
|
||||||
if (_versionFileUrl.size() == 0 ||
|
if (_versionFileUrl.size() == 0 ||
|
||||||
|
@ -153,36 +209,9 @@ void AssetsManager::update()
|
||||||
if (! checkUpdate()) return;
|
if (! checkUpdate()) return;
|
||||||
|
|
||||||
// Is package already downloaded?
|
// Is package already downloaded?
|
||||||
string downloadedVersion = CCUserDefault::sharedUserDefault()->getStringForKey(KEY_OF_DOWNLOADED_VERSION);
|
_downloadedVersion = CCUserDefault::sharedUserDefault()->getStringForKey(KEY_OF_DOWNLOADED_VERSION);
|
||||||
if (downloadedVersion != _version)
|
|
||||||
{
|
|
||||||
if (! downLoad()) return;
|
|
||||||
|
|
||||||
// Record downloaded version.
|
pthread_create(&_tid, NULL, assetsManagerDownloadAndUncompress, this);
|
||||||
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_DOWNLOADED_VERSION, _version.c_str());
|
|
||||||
CCUserDefault::sharedUserDefault()->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uncompress zip file.
|
|
||||||
if (! uncompress()) return;
|
|
||||||
|
|
||||||
// Record new version code.
|
|
||||||
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_VERSION, _version.c_str());
|
|
||||||
|
|
||||||
// Unrecord downloaded version code.
|
|
||||||
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_DOWNLOADED_VERSION, "");
|
|
||||||
|
|
||||||
CCUserDefault::sharedUserDefault()->flush();
|
|
||||||
|
|
||||||
// Set resource search path.
|
|
||||||
setSearchPath();
|
|
||||||
|
|
||||||
// Delete unloaded zip file.
|
|
||||||
string zipfileName = _storagePath + TEMP_PACKAGE_FILE_NAME;
|
|
||||||
if (remove(zipfileName.c_str()) != 0)
|
|
||||||
{
|
|
||||||
CCLOG("can not remove downloaded zip file");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetsManager::uncompress()
|
bool AssetsManager::uncompress()
|
||||||
|
@ -202,6 +231,7 @@ bool AssetsManager::uncompress()
|
||||||
{
|
{
|
||||||
CCLOG("can not read file global info of %s", outFileName.c_str());
|
CCLOG("can not read file global info of %s", outFileName.c_str());
|
||||||
unzClose(zipfile);
|
unzClose(zipfile);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer to hold data read from the zip file
|
// Buffer to hold data read from the zip file
|
||||||
|
@ -348,8 +378,19 @@ static size_t downLoadPackage(void *ptr, size_t size, size_t nmemb, void *userda
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int progressFunc(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
|
int assetsManagerProgressFunc(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
|
||||||
{
|
{
|
||||||
|
AssetsManager* manager = (AssetsManager*)ptr;
|
||||||
|
AssetsManager::Message *msg = new AssetsManager::Message();
|
||||||
|
msg->what = ASSETSMANAGER_MESSAGE_PROGRESS;
|
||||||
|
|
||||||
|
ProgressMessage *progressData = new ProgressMessage();
|
||||||
|
progressData->percent = (int)(nowDownloaded/totalToDownload*100);
|
||||||
|
progressData->manager = manager;
|
||||||
|
msg->obj = progressData;
|
||||||
|
|
||||||
|
manager->_schedule->sendMessage(msg);
|
||||||
|
|
||||||
CCLOG("downloading... %d%%", (int)(nowDownloaded/totalToDownload*100));
|
CCLOG("downloading... %d%%", (int)(nowDownloaded/totalToDownload*100));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -362,6 +403,7 @@ bool AssetsManager::downLoad()
|
||||||
FILE *fp = fopen(outFileName.c_str(), "wb");
|
FILE *fp = fopen(outFileName.c_str(), "wb");
|
||||||
if (! fp)
|
if (! fp)
|
||||||
{
|
{
|
||||||
|
sendErrorMessage(kCreateFile);
|
||||||
CCLOG("can not create file %s", outFileName.c_str());
|
CCLOG("can not create file %s", outFileName.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -372,11 +414,13 @@ bool AssetsManager::downLoad()
|
||||||
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, downLoadPackage);
|
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, downLoadPackage);
|
||||||
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, fp);
|
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, fp);
|
||||||
curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, false);
|
curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, false);
|
||||||
curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, progressFunc);
|
curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, assetsManagerProgressFunc);
|
||||||
|
curl_easy_setopt(_curl, CURLOPT_PROGRESSDATA, this);
|
||||||
res = curl_easy_perform(_curl);
|
res = curl_easy_perform(_curl);
|
||||||
curl_easy_cleanup(_curl);
|
curl_easy_cleanup(_curl);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
{
|
{
|
||||||
|
sendErrorMessage(kNetwork);
|
||||||
CCLOG("error when download package");
|
CCLOG("error when download package");
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return false;
|
return false;
|
||||||
|
@ -429,4 +473,132 @@ void AssetsManager::deleteVersion()
|
||||||
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_VERSION, "");
|
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_VERSION, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetsManager::setDelegate(AssetsManagerDelegateProtocol *delegate)
|
||||||
|
{
|
||||||
|
_delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManager::setConnectionTimeout(unsigned int timeout)
|
||||||
|
{
|
||||||
|
_connectionTimeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int AssetsManager::getConnectionTimeout()
|
||||||
|
{
|
||||||
|
return _connectionTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManager::sendErrorMessage(AssetsManager::ErrorCode code)
|
||||||
|
{
|
||||||
|
Message *msg = new Message();
|
||||||
|
msg->what = ASSETSMANAGER_MESSAGE_ERROR;
|
||||||
|
|
||||||
|
ErrorMessage *errorMessage = new ErrorMessage();
|
||||||
|
errorMessage->code = code;
|
||||||
|
errorMessage->manager = this;
|
||||||
|
msg->obj = errorMessage;
|
||||||
|
|
||||||
|
_schedule->sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of AssetsManagerHelper
|
||||||
|
|
||||||
|
AssetsManager::Helper::Helper()
|
||||||
|
{
|
||||||
|
_messageQueue = new list<Message*>();
|
||||||
|
pthread_mutex_init(&_messageQueueMutex, NULL);
|
||||||
|
CCDirector::sharedDirector()->getScheduler()->scheduleUpdateForTarget(this, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetsManager::Helper::~Helper()
|
||||||
|
{
|
||||||
|
CCDirector::sharedDirector()->getScheduler()->unscheduleAllForTarget(this);
|
||||||
|
delete _messageQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManager::Helper::sendMessage(Message *msg)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&_messageQueueMutex);
|
||||||
|
_messageQueue->push_back(msg);
|
||||||
|
pthread_mutex_unlock(&_messageQueueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManager::Helper::update(float dt)
|
||||||
|
{
|
||||||
|
Message *msg = NULL;
|
||||||
|
|
||||||
|
// Returns quickly if no message
|
||||||
|
pthread_mutex_lock(&_messageQueueMutex);
|
||||||
|
if (0 == _messageQueue->size())
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&_messageQueueMutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets message
|
||||||
|
msg = *(_messageQueue->begin());
|
||||||
|
_messageQueue->pop_front();
|
||||||
|
pthread_mutex_unlock(&_messageQueueMutex);
|
||||||
|
|
||||||
|
switch (msg->what) {
|
||||||
|
case ASSETSMANAGER_MESSAGE_UPDATE_SUCCEED:
|
||||||
|
handleUpdateSucceed(msg);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ASSETSMANAGER_MESSAGE_RECORD_DOWNLOADED_VERSION:
|
||||||
|
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_DOWNLOADED_VERSION,
|
||||||
|
((AssetsManager*)msg->obj)->_version.c_str());
|
||||||
|
CCUserDefault::sharedUserDefault()->flush();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ASSETSMANAGER_MESSAGE_PROGRESS:
|
||||||
|
if (((ProgressMessage*)msg->obj)->manager->_delegate)
|
||||||
|
{
|
||||||
|
((ProgressMessage*)msg->obj)->manager->_delegate->onProgress(((ProgressMessage*)msg->obj)->percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (ProgressMessage*)msg->obj;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ASSETSMANAGER_MESSAGE_ERROR:
|
||||||
|
// error call back
|
||||||
|
if (((ErrorMessage*)msg->obj)->manager->_delegate)
|
||||||
|
{
|
||||||
|
((ErrorMessage*)msg->obj)->manager->_delegate->onError(((ErrorMessage*)msg->obj)->code);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ((ErrorMessage*)msg->obj);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetsManager::Helper::handleUpdateSucceed(Message *msg)
|
||||||
|
{
|
||||||
|
AssetsManager* manager = (AssetsManager*)msg->obj;
|
||||||
|
|
||||||
|
// Record new version code.
|
||||||
|
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_VERSION, manager->_version.c_str());
|
||||||
|
|
||||||
|
// Unrecord downloaded version code.
|
||||||
|
CCUserDefault::sharedUserDefault()->setStringForKey(KEY_OF_DOWNLOADED_VERSION, "");
|
||||||
|
CCUserDefault::sharedUserDefault()->flush();
|
||||||
|
|
||||||
|
// Set resource search path.
|
||||||
|
manager->setSearchPath();
|
||||||
|
|
||||||
|
// Delete unloaded zip file.
|
||||||
|
string zipfileName = manager->_storagePath + TEMP_PACKAGE_FILE_NAME;
|
||||||
|
if (remove(zipfileName.c_str()) != 0)
|
||||||
|
{
|
||||||
|
CCLOG("can not remove downloaded zip file %s", zipfileName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager) manager->_delegate->onSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
NS_CC_EXT_END;
|
NS_CC_EXT_END;
|
||||||
|
|
|
@ -27,12 +27,15 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "cocos2d.h"
|
#include "cocos2d.h"
|
||||||
#include "ExtensionMacros.h"
|
#include "ExtensionMacros.h"
|
||||||
|
|
||||||
NS_CC_EXT_BEGIN
|
NS_CC_EXT_BEGIN
|
||||||
|
|
||||||
|
class AssetsManagerDelegateProtocol;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This class is used to auto update resources, such as pictures or scripts.
|
* This class is used to auto update resources, such as pictures or scripts.
|
||||||
* The updated package should be a zip file. And there should be a file named
|
* The updated package should be a zip file. And there should be a file named
|
||||||
|
@ -43,28 +46,36 @@ class AssetsManager
|
||||||
public:
|
public:
|
||||||
enum ErrorCode
|
enum ErrorCode
|
||||||
{
|
{
|
||||||
ServerNotAvailable, /** server address error or timeout */
|
// Error caused by creating a file to store downloaded data
|
||||||
TimeOut,
|
kCreateFile,
|
||||||
|
/** Error caused by network
|
||||||
|
-- network unavaivable
|
||||||
|
-- timeout
|
||||||
|
-- ...
|
||||||
|
*/
|
||||||
|
kNetwork,
|
||||||
|
/** There is not a new version
|
||||||
|
*/
|
||||||
|
kNoNewVersion,
|
||||||
|
/** Error caused in uncompressing stage
|
||||||
|
-- can not open zip file
|
||||||
|
-- can not read file global information
|
||||||
|
-- can not read file information
|
||||||
|
-- can not create a directory
|
||||||
|
-- ...
|
||||||
|
*/
|
||||||
|
kUncompress,
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Default constructor. You should set server address later.
|
|
||||||
AssetsManager();
|
|
||||||
|
|
||||||
/* @brief Creates a AssetsManager with new package url and version code url.
|
|
||||||
* AssetsManager will use the value returned by CCFileUtils::getWritablePath() as storage path.
|
|
||||||
*
|
|
||||||
* @param packageUrl URL of new package, the package should be a zip file.
|
|
||||||
* @param versionFileUrl URL of version file. It should contain version code of new package.
|
|
||||||
*/
|
|
||||||
AssetsManager(const char* packageUrl, const char* versionFileUrl);
|
|
||||||
|
|
||||||
/* @brief Creates a AssetsManager with new package url, version code url and storage path.
|
/* @brief Creates a AssetsManager with new package url, version code url and storage path.
|
||||||
*
|
*
|
||||||
* @param packageUrl URL of new package, the package should be a zip file.
|
* @param packageUrl URL of new package, the package should be a zip file.
|
||||||
* @param versionFileUrl URL of version file. It should contain version code of new package.
|
* @param versionFileUrl URL of version file. It should contain version code of new package.
|
||||||
* @param storagePath The path to store downloaded resources.
|
* @param storagePath The path to store downloaded resources.
|
||||||
*/
|
*/
|
||||||
AssetsManager(const char* packageUrl, const char* versionFileUrl, const char* storagePath);
|
AssetsManager(const char* packageUrl = NULL, const char* versionFileUrl = NULL, const char* storagePath = NULL);
|
||||||
|
|
||||||
|
virtual ~AssetsManager();
|
||||||
|
|
||||||
/* @brief Check out if there is a new version resource.
|
/* @brief Check out if there is a new version resource.
|
||||||
* You may use this method before updating, then let user determine whether
|
* You may use this method before updating, then let user determine whether
|
||||||
|
@ -112,12 +123,55 @@ public:
|
||||||
*/
|
*/
|
||||||
void setStoragePath(const char* storagePath);
|
void setStoragePath(const char* storagePath);
|
||||||
|
|
||||||
|
/** @brief Sets delegate, the delegate will receive messages
|
||||||
|
*/
|
||||||
|
void setDelegate(AssetsManagerDelegateProtocol *delegate);
|
||||||
|
|
||||||
|
/** @brief Sets connection time out in seconds
|
||||||
|
*/
|
||||||
|
void setConnectionTimeout(unsigned int timeout);
|
||||||
|
|
||||||
|
/** @brief Gets connection time out in secondes
|
||||||
|
*/
|
||||||
|
unsigned int getConnectionTimeout();
|
||||||
|
|
||||||
|
/* downloadAndUncompress is the entry of a new thread
|
||||||
|
*/
|
||||||
|
friend void* assetsManagerDownloadAndUncompress(void*);
|
||||||
|
friend int assetsManagerProgressFunc(void *, double, double, double, double);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool downLoad();
|
bool downLoad();
|
||||||
void checkStoragePath();
|
void checkStoragePath();
|
||||||
bool uncompress();
|
bool uncompress();
|
||||||
bool createDirectory(const char *path);
|
bool createDirectory(const char *path);
|
||||||
void setSearchPath();
|
void setSearchPath();
|
||||||
|
void sendErrorMessage(ErrorCode code);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef struct _Message
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
_Message() : what(0), obj(NULL){}
|
||||||
|
unsigned int what; // message type
|
||||||
|
void* obj;
|
||||||
|
} Message;
|
||||||
|
|
||||||
|
class Helper : public cocos2d::CCObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Helper();
|
||||||
|
~Helper();
|
||||||
|
|
||||||
|
virtual void update(float dt);
|
||||||
|
void sendMessage(Message *msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleUpdateSucceed(Message *msg);
|
||||||
|
|
||||||
|
std::list<Message*> *_messageQueue;
|
||||||
|
pthread_mutex_t _messageQueueMutex;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! The path to store downloaded resources.
|
//! The path to store downloaded resources.
|
||||||
|
@ -129,7 +183,33 @@ private:
|
||||||
std::string _packageUrl;
|
std::string _packageUrl;
|
||||||
std::string _versionFileUrl;
|
std::string _versionFileUrl;
|
||||||
|
|
||||||
|
std::string _downloadedVersion;
|
||||||
|
|
||||||
CURL *_curl;
|
CURL *_curl;
|
||||||
|
Helper *_schedule;
|
||||||
|
pthread_t _tid;
|
||||||
|
unsigned int _connectionTimeout;
|
||||||
|
|
||||||
|
AssetsManagerDelegateProtocol *_delegate; // weak reference
|
||||||
|
};
|
||||||
|
|
||||||
|
class AssetsManagerDelegateProtocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* @brief Call back function for error
|
||||||
|
@param errorCode Type of error
|
||||||
|
*/
|
||||||
|
virtual void onError(AssetsManager::ErrorCode errorCode) {};
|
||||||
|
/** @brief Call back function for recording downloading percent
|
||||||
|
@param percent How much percent downloaded
|
||||||
|
@warn This call back function just for recording downloading percent.
|
||||||
|
AssetsManager will do some other thing after downloading, you should
|
||||||
|
write code in onSuccess() after downloading.
|
||||||
|
*/
|
||||||
|
virtual void onProgress(int percent) {};
|
||||||
|
/** @brief Call back function for success
|
||||||
|
*/
|
||||||
|
virtual void onSuccess() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_CC_EXT_END;
|
NS_CC_EXT_END;
|
||||||
|
|
|
@ -77,6 +77,7 @@ UpdateLayer::UpdateLayer()
|
||||||
: pItemEnter(NULL)
|
: pItemEnter(NULL)
|
||||||
, pItemReset(NULL)
|
, pItemReset(NULL)
|
||||||
, pItemUpdate(NULL)
|
, pItemUpdate(NULL)
|
||||||
|
, pProgressLabel(NULL)
|
||||||
, isUpdateItemClicked(false)
|
, isUpdateItemClicked(false)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
@ -90,6 +91,8 @@ UpdateLayer::~UpdateLayer()
|
||||||
|
|
||||||
void UpdateLayer::update(cocos2d::CCObject *pSender)
|
void UpdateLayer::update(cocos2d::CCObject *pSender)
|
||||||
{
|
{
|
||||||
|
pProgressLabel->setString("");
|
||||||
|
|
||||||
// update resources
|
// update resources
|
||||||
getAssetsManager()->update();
|
getAssetsManager()->update();
|
||||||
|
|
||||||
|
@ -98,6 +101,8 @@ void UpdateLayer::update(cocos2d::CCObject *pSender)
|
||||||
|
|
||||||
void UpdateLayer::reset(cocos2d::CCObject *pSender)
|
void UpdateLayer::reset(cocos2d::CCObject *pSender)
|
||||||
{
|
{
|
||||||
|
pProgressLabel->setString(" ");
|
||||||
|
|
||||||
// Remove downloaded files
|
// Remove downloaded files
|
||||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
|
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
|
||||||
string command = "rm -r ";
|
string command = "rm -r ";
|
||||||
|
@ -152,6 +157,10 @@ bool UpdateLayer::init()
|
||||||
menu->setPosition(ccp(0,0));
|
menu->setPosition(ccp(0,0));
|
||||||
addChild(menu);
|
addChild(menu);
|
||||||
|
|
||||||
|
pProgressLabel = CCLabelTTF::create("", "Arial", 20);
|
||||||
|
pProgressLabel->setPosition(ccp(100, 50));
|
||||||
|
addChild(pProgressLabel);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +173,8 @@ AssetsManager* UpdateLayer::getAssetsManager()
|
||||||
pAssetsManager = new AssetsManager("https://raw.github.com/minggo/AssetsManagerTest/master/package.zip",
|
pAssetsManager = new AssetsManager("https://raw.github.com/minggo/AssetsManagerTest/master/package.zip",
|
||||||
"https://raw.github.com/minggo/AssetsManagerTest/master/version",
|
"https://raw.github.com/minggo/AssetsManagerTest/master/version",
|
||||||
pathToSave.c_str());
|
pathToSave.c_str());
|
||||||
|
pAssetsManager->setDelegate(this);
|
||||||
|
pAssetsManager->setConnectionTimeout(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pAssetsManager;
|
return pAssetsManager;
|
||||||
|
@ -190,3 +201,28 @@ void UpdateLayer::createDownloadedDir()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateLayer::onError(AssetsManager::ErrorCode errorCode)
|
||||||
|
{
|
||||||
|
if (errorCode == AssetsManager::kNoNewVersion)
|
||||||
|
{
|
||||||
|
pProgressLabel->setString("no new version");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorCode == AssetsManager::kNetwork)
|
||||||
|
{
|
||||||
|
pProgressLabel->setString("network error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateLayer::onProgress(int percent)
|
||||||
|
{
|
||||||
|
char progress[20];
|
||||||
|
snprintf(progress, 20, "downloading %d%%", percent);
|
||||||
|
pProgressLabel->setString(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateLayer::onSuccess()
|
||||||
|
{
|
||||||
|
pProgressLabel->setString("download ok");
|
||||||
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
virtual void applicationWillEnterForeground();
|
virtual void applicationWillEnterForeground();
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateLayer : public cocos2d::CCLayer
|
class UpdateLayer : public cocos2d::CCLayer, public cocos2d::extension::AssetsManagerDelegateProtocol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UpdateLayer();
|
UpdateLayer();
|
||||||
|
@ -55,6 +55,10 @@ public:
|
||||||
void reset(cocos2d::CCObject *pSender);
|
void reset(cocos2d::CCObject *pSender);
|
||||||
void update(cocos2d::CCObject *pSender);
|
void update(cocos2d::CCObject *pSender);
|
||||||
|
|
||||||
|
virtual void onError(cocos2d::extension::AssetsManager::ErrorCode errorCode);
|
||||||
|
virtual void onProgress(int percent);
|
||||||
|
virtual void onSuccess();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cocos2d::extension::AssetsManager* getAssetsManager();
|
cocos2d::extension::AssetsManager* getAssetsManager();
|
||||||
void createDownloadedDir();
|
void createDownloadedDir();
|
||||||
|
@ -62,6 +66,7 @@ private:
|
||||||
cocos2d::CCMenuItemFont *pItemEnter;
|
cocos2d::CCMenuItemFont *pItemEnter;
|
||||||
cocos2d::CCMenuItemFont *pItemReset;
|
cocos2d::CCMenuItemFont *pItemReset;
|
||||||
cocos2d::CCMenuItemFont *pItemUpdate;
|
cocos2d::CCMenuItemFont *pItemUpdate;
|
||||||
|
cocos2d::CCLabelTTF *pProgressLabel;
|
||||||
std::string pathToSave;
|
std::string pathToSave;
|
||||||
bool isUpdateItemClicked;
|
bool isUpdateItemClicked;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue