cocos2d-js直接解压运行本地zip文件

这几天在尝试使用cocos2d-js解压运行本地zip文件,用的是cocos2d-x 3.13版本,xcode8.2。之前想到的是既然在热更新的时候,已经有从服务端下载zip文件解压运行的接口,那么直接把解压运行的接口提取出来封装成单独一个接口应该也是可行的。因为之前我这边的热更新已经做好了,所以修改直接在我这个热更新demo上继续。热更新教程

1、分析热更新时下载解压zip文件的流程;
  1. 首先找到js代码中初始化AssetsManager的地方;
    这里写图片描述

  2. 然后按目录打开cocos2d-js-bindings.xcodeproj。/TestJs001/frameworks/cocos2d-x/cocos/scripting/js-bindings/proj.ios_mac;
    这里写图片描述

  3. 在此处搜索AssetsManager,定位到jsb_cocos2dx_extension_auto.cpp类,接下来就是在这里做文章了。
    这里写图片描述

  4. 通过在几个可能会调到的方法里添加了log发现,会调用到AssetsManager的构造函数。这样就可以直接去C++那边查看构造函数那边是如何做处理的了。
    这里写图片描述

  5. 按目录打开cocos2d_libs.xcodeproj。/TestJs001/frameworks/cocos2d-x/build/cocos2d_libs.xcodeproj;
    这里写图片描述

  6. 搜索找到AssetsManagerEx.h,及其构造函数。AssetsManagerEx(const std::string& manifestUrl, const std::string& storagePath);
    这里写图片描述

  7. 分析了下,加载过程,会发现在加载成功时会调用onSuccess方法,然后就会调用到这个decompressDownloadedZip(),再进而调用到decompress(),decompress一听就知道是干解压事情的,那么接下来就是在这个方法上动手啦。
    这里写图片描述


2、加入解压zip文件的接口.
  • 1 拷贝一份decompress方法,重新命名为decompressLocalZip,即
    bool AssetsManagerEx::decompressLocalZip(const std::string &zip),并在.h文件中添加相应头文件,注意要添加到public下,这样js-binding才能调用到。

  • 2 修改decompressLocalZip.cpp,

bool AssetsManagerEx::decompressLocalZip(const std::string &zip)
{
    CCLOG("AssetsManagerEx : decompressLocalZip  zip = %s  ..........." , zip.c_str());
    FileUtils* fileTtils = FileUtils::getInstance();
    //获得可写的具体文件路径
    std::string writeablePath = fileTtils->getWritablePath();
    size_t pos_0 = zip.find_last_of("/\\");
    if (pos_0 == std::string::npos)
    {
        CCLOG("pos_0.........zip not exit");
        return false;
    }
    std::string zipName = zip.substr(pos_0 + 1, strlen(zip.c_str()));
    log("zipName = %s",zipName.c_str());
    std::string xmlPath = writeablePath + zipName;
    log("xmlPath = %s",xmlPath.c_str());

    std::string curFullPath = fileTtils->fullPathForFilename(zip.c_str());

    CCLOG("AssetsManagerEx : decompress  fullPath = %s  ..........." , curFullPath.c_str());
    CCLOG("AssetsManagerEx : decompress  xmlPath = %s  ..........." , xmlPath.c_str());
    // Find root path for zip file
    size_t pos = xmlPath.find_last_of("/\\");
    if (pos == std::string::npos)
    {
        CCLOG("AssetsManagerEx : no root path specified for curFullPath file %s\n", curFullPath.c_str());
        return false;
    }
    const std::string rootPath = xmlPath.substr(0, pos+1);

    CCLOG("AssetsManagerEx : rootPath  = %s  ...........1111" , rootPath.c_str());
    CCLOG("AssetsManagerEx : getSuitableFOpen  zip = %s  ..........." , FileUtils::getInstance()->getSuitableFOpen(curFullPath).c_str());
    // Open the zip file
    unzFile zipfile = unzOpen(FileUtils::getInstance()->getSuitableFOpen(curFullPath).c_str());
    if (! zipfile)
    {
        CCLOG("AssetsManagerEx : can not open downloaded zip file %s\n", curFullPath.c_str());
        return false;
    }

    // Get info about the zip file
    unz_global_info global_info;
    if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK)
    {
        CCLOG("AssetsManagerEx : can not read file global info of %s\n", curFullPath.c_str());
        unzClose(zipfile);
        return false;
    }

    // Buffer to hold data read from the zip file
    char readBuffer[BUFFER_SIZE];
    // Loop to extract all files.
    uLong i;
    for (i = 0; i < global_info.number_entry; ++i)
    {
        // Get info about current file.
        unz_file_info fileInfo;
        char fileName[MAX_FILENAME];
        if (unzGetCurrentFileInfo(zipfile,
                                  &fileInfo,
                                  fileName,
                                  MAX_FILENAME,
                                  NULL,
                                  0,
                                  NULL,
                                  0) != UNZ_OK)
        {
            CCLOG("AssetsManagerEx : can not read compressed file info\n");
            unzClose(zipfile);
            return false;
        }
        const std::string fullPath = rootPath + fileName;
        CCLOG("AssetsManagerEx : create directory fullPath %s\n", fullPath.c_str());

        // Check if this entry is a directory or a file.
        const size_t filenameLength = strlen(fileName);
        if (fileName[filenameLength-1] == '/')
        {
            //There are not directory entry in some case.
            //So we need to create directory when decompressing file entry
            if ( !_fileUtils->createDirectory(basename(fullPath)) )
            {
                // Failed to create directory
                CCLOG("AssetsManagerEx : can not create directory %s\n", fullPath.c_str());
                unzClose(zipfile);
                return false;
            }
        }
        else
        {
            //  jsb depress zip xuyuanteng add 20170324
            std::string dir = basename(fullPath);
             CCLOG("AssetsManagerEx : basename dir %s\n", dir.c_str());
            if(!_fileUtils->isDirectoryExist(dir))
            {
                 CCLOG("AssetsManagerEx : isDirectoryExist   no  no  no");
                if(!_fileUtils->createDirectory(dir))
                {
                    // Failed to create directory
                    CCLOG("AssetsManagerEx : can not create directory %s\n", fullPath.c_str());
                    unzClose(zipfile);
                    return false;
                }

            }

            // Entry is a file, so extract it.
            // Open current file.
            if (unzOpenCurrentFile(zipfile) != UNZ_OK)
            {
                CCLOG("AssetsManagerEx : can not extract file %s\n", fileName);
                unzClose(zipfile);
                return false;
            }

            // Create a file to store current file.
            CCLOG("AssetsManagerEx : fullPath  =  %s\n", fullPath.c_str());
            CCLOG("AssetsManagerEx : fopen getSuitableFOpen fullPath =  %s\n", FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str());
            FILE *out = fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), "wb");
            if (!out)
            {
                CCLOG("AssetsManagerEx : can not create decompress destination file %s\n", fullPath.c_str());
                unzCloseCurrentFile(zipfile);
                unzClose(zipfile);
                return false;
            }

            // Write current file content to destinate file.
            int error = UNZ_OK;
            do
            {
                error = unzReadCurrentFile(zipfile, readBuffer, BUFFER_SIZE);
                if (error < 0)
                {
                    CCLOG("AssetsManagerEx : can not read zip file %s, error code is %d\n", fileName, error);
                    fclose(out);
                    unzCloseCurrentFile(zipfile);
                    unzClose(zipfile);
                    return false;
                }

                if (error > 0)
                {
                    fwrite(readBuffer, error, 1, out);
                }
            } while(error > 0);

            fclose(out);
        }

        unzCloseCurrentFile(zipfile);

        // Goto next entry listed in the zip file.
        if ((i+1) < global_info.number_entry)
        {
            if (unzGoToNextFile(zipfile) != UNZ_OK)
            {
                CCLOG("AssetsManagerEx : can not read next file for decompressing\n");
                unzClose(zipfile);
                return false;
            }
        }
    }

    unzClose(zipfile);
    return true;
}
  • 3 回到jsb_cocos2dx_extension_auto.hpp类,添加头文件
    bool js_cocos2dx_extension_AssetsManagerEx_decompressLocalZip(JSContext *cx, uint32_t argc, jsval *vp);,在jsb_cocos2dx_extension_auto.cpp中加入实现,
//jsb uncompress xuyuanteng add 20170324
bool js_cocos2dx_extension_AssetsManagerEx_decompressLocalZip(JSContext *cx, uint32_t argc, jsval *vp)
{
    cocos2d::log("js_cocos2dx_extension_AssetsManagerEx_decompressLocalZip......");

    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
    bool ok = true;
    JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
    js_proxy_t *proxy = jsb_get_js_proxy(obj);
    cocos2d::extension::AssetsManagerEx* cobj = (cocos2d::extension::AssetsManagerEx *)(proxy ? proxy->ptr : NULL);
    JSB_PRECONDITION2( cobj, cx, false, "js_cocos2dx_extension_AssetsManagerEx_decompressLocalZip : Invalid Native Object");
    if (argc == 1) {
        std::string arg0;
        ok &= jsval_to_std_string(cx, args.get(0), &arg0);
        JSB_PRECONDITION2(ok, cx, false, "js_cocos2dx_extension_Assetjs_cocos2dx_extension_AssetsManagerEx_decompressLocalZipsManagerEx_decompress : Error processing arguments");
        bool ret = cobj->decompressLocalZip(arg0);
        jsval jsret = JSVAL_NULL;
        jsret = BOOLEAN_TO_JSVAL(ret);
        args.rval().set(jsret);
        return true;
    }

    JS_ReportError(cx, "js_cocos2dx_extension_AssetsManagerEx_decompressLocalZip : wrong number of arguments: %d, was expecting %d", argc, 1);
    return false;
}
  • 4 在js_register_cocos2dx_extension_AssetsManagerEx方法里进行绑定。
    JS_FN("decompressLocalZip", js_cocos2dx_extension_AssetsManagerEx_decompressLocalZip, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),

  • 5 编译cocos2d_js_bindings工程,生成静态库后,放到cocos2d_libs.xcodeproj工程下,编译生成静态库。

  • 6 js调用代码如下。

    this._am = new jsb.AssetsManager("test", "test"); 
    this._am.retain();

    var isSucceed = this._am.decompressLocalZip("src/app.zip");
    cc.log("isSucceed = " + isSucceed);

    var storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "./");
    cc.log("storagePath is " + storagePath);
    //添加搜索路径
    jsb.fileUtils.addSearchPath(storagePath);
    //解压成功后运行场景
    if (isSucceed) {
            cc.loader.loadJs(["src/jsList.js"], function(){
                     cc.loader.loadJs(jsList, function(){
                            cc.director.runScene(new HelloWorldScene());
                        }); 
                     });
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值