cocos2d-x jsbinding 资源下载实现
cocos2dx没有直接给出资源下载的api,可能是因为资源的管理每个项目的需求不太一样,所以完整的资源下载功能需要我们自己去实现。
资源下载分为两部分,一部分是资源请求,另一部分是资源文件写入。资源请求模块,cocos2d-x封装了curl的功能,主要实现是extensions\network下的几个类,通过他们我们可以方便的实现Http请求的功能。资源的写入主要是利用fwrite函数将数据流写入文件。完成了C++模块的实现以后,我们要做的是绑定到js,这样我们就可以在js端发起请求,将资源下载到手机。这里C++绑定还有Http请求的封装主要借鉴了https://github.com/akira-cn/cocos2dx-cqwrap/blob/master/cqwrap/src/scripting/cqwrap_httprequest_manual.cpp 我在此的基础上做了一些改动,同时增加了文件的写入功能
#include "cqwrap_register_all_manual.h" #include "util/JsonHelper.h" #include "pattern/EventProxy.h"
#include <algorithm>
#include <sstream> #include "cocos-ext.h"
// 这个用于获取各个平台的资源缓存缓存路径,关于缓存路径,请看http://www.cnblogs.com/hzd822/p/3258641.html
#include "KT_ALL_PLATFORMS.h" USING_NS_CC_EXT; void js_register_cocos2dx_extension_httprequest(JSContext *cx, JSObject *global); JSClass *jsb_HttpRequest_Class; JSObject *jsb_HttpRequest_prototype; void register_cqwrap_httprequest(JSContext* cx, JSObject* obj) { // first, try to get the ns jsval nsval; JSObject *ns; JS_GetProperty(cx, obj, "cc", &nsval); if (nsval == JSVAL_VOID) { ns = JS_NewObject(cx, NULL, NULL, NULL); nsval = OBJECT_TO_JSVAL(ns); JS_SetProperty(cx, obj, "cc", &nsval); } else { JS_ValueToObject(cx, nsval, &ns); } obj = ns; js_register_cocos2dx_extension_httprequest(cx, obj); } // 这个类对CCHttpRequest的封装
class HttpRequest: public CCObject{ protected: CCHttpRequest* m_request; std::vector<std::string> m_headers; int m_writefile; std::string m_url; struct xorStruct { xorStruct(char value) : m_value(value) {} char m_value; char operator()(char in) const { return in ^ m_value; } }; void responseCallback(cocos2d::CCNode *sender, void *data){ CCHttpResponse *response = (CCHttpResponse*)data; if (!response) { CCLog("no response..."); return; } int statusCode = response->getResponseCode(); char statusString[64] = {}; sprintf(statusString, "HTTP Status Code: %d", statusCode); CCLOG("response code: %d", statusCode); if (!response->isSucceed()) { CCLOG("response failed"); CCLOG("error buffer: %s", response->getErrorBuffer()); JsonData* msg = new JsonData(); (*msg)["data"] = response->getErrorBuffer(); PROXY_FIRE("error", msg); CC_SAFE_DELETE(msg); return; } JsonData* msg = new JsonData(); // dump data std::vector<char> *buffer = response->getResponseData(); if (m_writefile == 1){ // 获取相对路径 std::string relativePath = m_url.substr(m_urlhostNum); std::string filePath; filePath = kt_library_path(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) filePath = filePath + "/Caches/"; #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) filePath = filePath + "/Caches/"; #endif filePath.append(relativePath); this->writeToFile(filePath.c_str(), *buffer); (*msg)["status"] = statusCode; }else{ std::string buf(buffer->begin(),buffer->end()); (*msg)["data"] = buf.c_str(); } PROXY_FIRE("complete", msg); CC_SAFE_DELETE(msg); }; public:
int m_urlhostNum; void send(const char* buffer = NULL){ if(m_request != NULL){ if(NULL != buffer){ m_request->setRequestData(buffer, sizeof buffer); } m_request->setHeaders(m_headers); CCHttpClient::getInstance()->send(m_request); CC_SAFE_RELEASE_NULL(m_request); m_headers.clear(); } }; // 文件写入
bool writeToFile(const char *filePath,std::vector<char> _responseData) { FILE* fout = fopen(filePath, "wb+"); if (fout == NULL) return false; if (_responseData.size() > 0) { if (fwrite(&_responseData[0], sizeof(char), _responseData.size(), fout) != _responseData.size()) { fclose(fout); return false; } } fclose(fout); return true; } void setRequestHeader(std::string key, std::string content){ if(m_request != NULL){ key += ": "; key += content; m_headers.push_back(key); } }; void setRequestData(std::string* requestData){ if(m_request != NULL){ m_request->setRequestData(requestData->c_str(),requestData->length()); } }; void open(CCHttpRequest::HttpRequestType type, const char* url,int writeFile){ CC_SAFE_RELEASE_NULL(m_request); m_writefile = writeFile; m_request = new CCHttpRequest(); m_request->setUrl(url); m_request->setRequestType(type); m_request->setResponseCallback(this, callfuncND_selector(HttpRequest::responseCallback)); m_url = url; }; HttpRequest(){ m_request = NULL; m_headers = std::vector<std::string>(); m_writefile = 0; m_urlhostNum = 32; }; ~HttpRequest(){ CC_SAFE_RELEASE_NULL(m_request); }; }; // 从这里开始是将C++类绑定到js,使js可以调用C++函数
JSBool js_cocos2dx_extension_HttpRequest_setRequestHeader(JSContext *cx, uint32_t argc, jsval *vp){ jsval *argv = JS_ARGV(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if(argc == 2){ std::string* key = new std::string(); do { JSBool ok = jsval_to_std_string(cx, argv[0], key); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); std::string* value = new std::string(); do { JSBool ok = jsval_to_std_string(cx, argv[1], value); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); cobj->setRequestHeader(*key, *value); JS_SET_RVAL(cx, vp, JSVAL_VOID); CC_SAFE_DELETE(key); CC_SAFE_DELETE(value); return JS_TRUE; } JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); return JS_FALSE; } JSBool js_cocos2dx_extension_HttpRequest_setRequestData(JSContext *cx, uint32_t argc, jsval *vp){ jsval *argv = JS_ARGV(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if(argc == 1){ std::string* requestData = new std::string(); do { JSBool ok = jsval_to_std_string(cx, argv[0], requestData); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); cobj->setRequestData(requestData); JS_SET_RVAL(cx, vp, JSVAL_VOID); CC_SAFE_DELETE(requestData); return JS_TRUE; } JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); return JS_FALSE; } JSBool js_cocos2dx_extension_HttpRequest_open(JSContext *cx, uint32_t argc, jsval *vp){ jsval *argv = JS_ARGV(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if(argc == 2 || argc == 3 || argc == 4){ std::string* method = new std::string(); do { JSBool ok = jsval_to_std_string(cx, argv[0], method); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); std::string* url = new std::string(); do { JSBool ok = jsval_to_std_string(cx, argv[1], url); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); int writeFile = 1; if (argc == 3){ do { JSBool ok = jsval_to_int32(cx, argv[2], &writeFile); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); } int urlhostNum;
if (argc == 4){
do {
JSBool ok = jsval_to_int32(cx, argv[3], &urlhostNum); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); cobj->m_urlhostNum = urlhostNum; } while (0); } if(*method == "POST"){ cobj->open(CCHttpRequest::kHttpPost, url->c_str(),writeFile); }else{ cobj->open(CCHttpRequest::kHttpGet, url->c_str(),writeFile); } JS_SET_RVAL(cx, vp, JSVAL_VOID); CC_SAFE_DELETE(url); CC_SAFE_DELETE(method); return JS_TRUE; } JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); return JS_FALSE; } JSBool js_cocos2dx_extension_HttpRequest_send(JSContext *cx, uint32_t argc, jsval *vp){ jsval *argv = JS_ARGV(cx, vp); JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if(argc == 1){ std::string* data = new std::string(); do { JSBool ok = jsval_to_std_string(cx, argv[0], data); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments"); } while (0); cobj->send(data->c_str()); JS_SET_RVAL(cx, vp, JSVAL_VOID); CC_SAFE_DELETE(data); return JS_TRUE; } if(argc == 0){ cobj->send(); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); return JS_FALSE; } JSBool js_cocos2dx_extension_HttpRequest_oncomplete(JSContext *cx, uint32_t argc, jsval *vp){ JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_FALSE; } JSBool js_cocos2dx_extension_HttpRequest_onerror(JSContext *cx, uint32_t argc, jsval *vp){ JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } void js_cocos2dx_extension_HttpRequest_finalize(JSFreeOp *fop, JSObject *obj){ } JSBool js_cocos2dx_extension_HttpRequest_constructor(JSContext *cx, uint32_t argc, jsval *vp){ if(argc == 0){ HttpRequest* cobj = new HttpRequest(); cocos2d::CCObject *_ccobj = dynamic_cast<cocos2d::CCObject *>(cobj); if (_ccobj) { _ccobj->autorelease(); } TypeTest<cocos2d::extension::CCHttpRequest> t; js_type_class_t *typeClass; uint32_t typeId = t.s_id(); HASH_FIND_INT(_js_global_type_ht, &typeId, typeClass); assert(typeClass); JSObject *obj = JS_NewObject(cx, typeClass->jsclass, typeClass->proto, typeClass->parentProto); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); // link the native object with the javascript object js_proxy_t *p; JS_NEW_PROXY(p, cobj, obj); JS_AddNamedObjectRoot(cx, &p->obj, "HttpRequest"); return JS_TRUE; } JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); return JS_FALSE; } void js_register_cocos2dx_extension_httprequest(JSContext *cx, JSObject *global) { jsb_HttpRequest_Class = (JSClass *)calloc(1, sizeof(JSClass)); jsb_HttpRequest_Class->name = "HttpRequest"; jsb_HttpRequest_Class->addProperty = JS_PropertyStub; jsb_HttpRequest_Class->delProperty = JS_PropertyStub; jsb_HttpRequest_Class->getProperty = JS_PropertyStub; jsb_HttpRequest_Class->setProperty = JS_StrictPropertyStub; jsb_HttpRequest_Class->enumerate = JS_EnumerateStub; jsb_HttpRequest_Class->resolve = JS_ResolveStub; jsb_HttpRequest_Class->convert = JS_ConvertStub; jsb_HttpRequest_Class->finalize = js_cocos2dx_extension_HttpRequest_finalize; jsb_HttpRequest_Class->flags = JSCLASS_HAS_RESERVED_SLOTS(2); static JSPropertySpec properties[] = { {0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} }; static JSFunctionSpec funcs[] = { JS_FN("oncomplete",js_cocos2dx_extension_HttpRequest_oncomplete, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("onerror",js_cocos2dx_extension_HttpRequest_onerror, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("send",js_cocos2dx_extension_HttpRequest_send, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("open",js_cocos2dx_extension_HttpRequest_open, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setRequestHeader",js_cocos2dx_extension_HttpRequest_setRequestHeader, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FS_END }; jsb_HttpRequest_prototype = JS_InitClass( cx, global, jsb_HttpRequest_prototype, jsb_HttpRequest_Class, js_cocos2dx_extension_HttpRequest_constructor, 0, // constructor properties, funcs, NULL, // no static properties NULL); // make the class enumerable in the registered namespace JSBool found; JS_SetPropertyAttributes(cx, global, "HttpRequest", JSPROP_ENUMERATE | JSPROP_READONLY, &found); // add the proto and JSClass to the type->js info hash table TypeTest<cocos2d::extension::CCHttpRequest> t; js_type_class_t *p; uint32_t typeId = t.s_id(); HASH_FIND_INT(_js_global_type_ht, &typeId, p); if (!p) { p = (js_type_class_t *)malloc(sizeof(js_type_class_t)); p->type = typeId; p->jsclass = jsb_HttpRequest_Class; p->proto = jsb_HttpRequest_prototype; p->parentProto = NULL; HASH_ADD_INT(_js_global_type_ht, type, p); } }
绑定完之后,js的调用就很简单了
// 创建http请求,请求远程图片
var httpRequest = cc.HttpRequest();
httpRequest.open('GET',fullPath);
httpRequest.send();
httpRequest.oncomplete = function (evt){
if (evt.status == 200){
cc.log(fullPath+'------downLoad success');
// 下载成功
}
} httpRequest.onerror = function (evt){
cc.log(fullPath+'------downLoad error');
}
}
cocos2d-x jsbinding 资源下载实现的更多相关文章
- Qt资源下载、安装、配置
(一)资源下载: 硕士毕业论文要做一个仿真平台,在linux环境下利用Qt开发. 自己有一定的c/c++基础,Qt是零基础接触.所以,经过一番查找,发现youtube一个外国友人Bryan从零开始教Q ...
- Linux Shell编程学习笔记——目录(附笔记资源下载)
LinuxShell编程学习笔记目录附笔记资源下载 目录(?)[-] 写在前面 第一部分 Shell基础编程 第二部分 Linux Shell高级编程技巧 资源下载 写在前面 最近花了些时间学习She ...
- [移动网关]2G环境下资源下载有一定概率失败,客户端日志显示收到403错误
2G环境下资源下载有一定概率失败,客户端日志显示收到403错误 问题现象: 测试同学在使用联通号码在移动网络环境下,访问连接得到的response_code出现是403,导致资源读取失败表情显示异常. ...
- 我的Unity学习笔记之——Unity中从网站下载ab资源+下载存储一条龙
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Net ...
- OSGI嵌入tomcat应用服务器(gem-web)——资源下载
Gem-Web官网介绍: 官网地址:https://www.eclipse.org/gemini/web/download/milestones.php 1.1. 官方正式发布版 https://ww ...
- 《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误
转载于:https://blog.csdn.net/aqi00/article/details/73065392 资源下载 下面是<Android Studio开发实战 从零基础到App上线&g ...
- Nginx配置资源下载目录
访问我的博客 之前在网上找 CentOs 的镜像的时候,发现了阿里云的这个镜像源,速度蛮快的.今天也来搭建一个类似的站,使用 nginx 作为资源下载服务器. 图片详情: 安装 Nginx 参考这篇教 ...
- krpano资源下载及还原全景图
krpano资源下载及还原全景图 现在全景云平台有大量的全景图资源,就存在了如何下载的需求. 原理:1.云平台多数使用krpano内核,首先需要将全景云平台中被krpano切成的全景图碎片下载下来,并 ...
- wppay免登录付费查看隐藏内容/付费资源下载
WPPAY是一款模板兔开发的免登录的付费查看内容/付费下载资源WordPress插件,WPPAY不需要用户注册登录即可支付查看隐藏内容,把整个流程做到极简.发布文章时要隐藏的内容可以利用短代码: [w ...
随机推荐
- Python 统计文本中单词的个数
1.读文件,通过正则匹配 def statisticWord(): line_number = 0 words_dict = {} with open (r'D:\test\test.txt',enc ...
- c++数组、字符串操作
一.数组操作 1.数组初始化1-1一维数组初始化:标准方式一: int value[100]; // value[i]的值不定,没有初始化标准方式二: int value[100] = {1,2}; ...
- Strassen算法
如题,该算法是来自德国的牛逼的数学家strassen搞出来的,因为把n*n矩阵之间的乘法复杂度降低到n^(lg7)(lg的底是2),一开始想当然地认为朴素的做法是n^3,哪里还能有复杂度更低的做法,但 ...
- JVM性能优化,提高Java的伸缩性
很多程序员在解决JVM性能问题的时候,花开了很多时间去调优应用程序级别的性能瓶颈,当你读完这本系列文章之后你会发现我可能更加系统地看待这类的问题.我说过JVM的自身技术限制了Java企业级应用的伸缩性 ...
- Uber新功能:隐藏司机乘客们的手机号码
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 使用「max-height」实现自适应高度
.tab-content{ max-height: 0; overflow: hidden; -webkit-transition: max-height .8s; -moz-transition: ...
- 关于Windows Azure 地缘组(Affinity Groups)
最近在和一些客户和朋友的沟通中,发现Windows Azure地缘组概念很少有了解.我的建议是使用地缘组来优化同一区域内的网络访问速度.如果我的说法有误,欢迎大家指正. 关于“地缘组”的概念(摘自MS ...
- vimdiff
[vimdiff] 启动方法 首先保证系统中的diff命令是可用的.Vim的diff模式是依赖于diff命令的.Vimdiff的基本用法就是: # vimdiff FILE_LEFT FILE_RIG ...
- USB -- BULK_ONLY和UFI协议
2 BULK_ONLY和UFI协议 Bulk—Only协议是USB组织针对大容量存储设备制定的一种块存储类协议,目前已经普遍应用于各种移动存储设备. USB设备分为5大类,即显示器.通信设备.音频设备 ...
- poj 2299 Ultra-QuickSort(求逆序对)
Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 52778 Accepted: 19348 ...