zoukankan      html  css  js  c++  java
  • cocos2d-x jsbinding 资源下载实现

        cocos2dx没有直接给出资源下载的api,可能是因为资源的管理每个项目的需求不太一样,所以完整的资源下载功能需要我们自己去实现。

        资源下载分为两部分,一部分是资源请求,另一部分是资源文件写入。资源请求模块,cocos2d-x封装了curl的功能,主要实现是extensions etwork下的几个类,通过他们我们可以方便的实现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');
                }
            }
    

      

  • 相关阅读:
    我的WCF之旅(1):创建一个简单的WCF程序
    与众不同 windows phone (15) Media(媒体)之后台播放音频
    与众不同 windows phone (14) Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成
    与众不同 windows phone (10) Push Notification(推送通知)之推送 Tile 通知, 推送自定义信息
    与众不同 windows phone (17) Graphic and Animation(画图和动画)
    与众不同 windows phone (5) Chooser(选择器)
    与众不同 windows phone (26) Contacts and Calendar(联系人和日历)
    与众不同 windows phone (7) Local Database(本地数据库)
    与众不同 windows phone (19) Device(设备)之陀螺仪传感器, Motion API
    与众不同 windows phone (16) Media(媒体)之编辑图片, 保存图片到相册, 与图片的上下文菜单“应用程序...”和“共享...”关联, 与 Windows Phone 的图片中心集成
  • 原文地址:https://www.cnblogs.com/zhepama/p/3288574.html
Copyright © 2011-2022 走看看