Cocos2d-x Android Direct load download to SD Zip resource file

Source: Internet
Author: User
Tags fread

A recent company to do a cocos-x project, this project is 2.2.6 version of the Cocos-x C + + version, Cocos older version. Because the packaged apk exceeds 300M, and the resource cannot be hot updated. Face these two problems. We discussed how to change the package to within 50m and update the new theme online as soon as possible, and studied the bottom of the cocos for a moment. Understand that Cocos can be


Ccfileutils::sharedfileutils ()->addsearchpath (path);

Such a way to load the resources in SD, and then we made the first version. How resources are loaded:

1. Download the resources to the corresponding directory in SD. Combine xutils to download to the corresponding SD directory.

  Httputils http = new Httputils ();        Http.configrequestthreadpoolsize (maxdownloadthread);        httphandler<file> handler = Http.download (Downloadinfo.getdownloadurl (), Downloadinfo.getfilesavepath (), Downloadinfo.isautoresume (), Downloadinfo.isautorename (), managercallback);        


2. Then unzip to the corresponding directory.

            /** * File Resolution * * @param files * zip file to unzip * @param savepath * Extracted to the path * @return * */Private Void Dounzip (St                Ring FilePath, String Savepath, Unziplistener unziplistener) {File File = new file (FilePath);                Debug.printlili ("Sdcardmanger dounzip"); String unzipfile = File.getabsolutepath (); The extracted filename contains the path try {//File Olddirec = file;//Unzip the path (in order to get the path)//                    Saved folder String parent = Savepath;                    Zipinputstream Zin = new Zipinputstream (new FileInputStream (Unzipfile));                    ZipEntry entry;  Create folder while ((entry = Zin.getnextentry ()) = null) {if (Entry.isdirectory ())      {File directory = new file (parent, Entry.getname ());                      if (!directory.exists ()) if (!directory.mkdirs ())                            Break                        Zin.closeentry ();                            } if (!entry.isdirectory ()) {File MyFile = new File (Entry.getname ());                            Output path String ofile = parent;                            File fo = new file (ofile);                            if (!fo.exists ()) {Fo.mkdir ();                            } String Filesavepath = ofile + Myfile.getpath ();                            Debug.printlili ("Unzip path:" + Filesavepath);                            FileOutputStream fout = new FileOutputStream (ofile + myfile.getpath ());                            DataOutputStream dout = new DataOutputStream (fout);                         Byte[] B = new byte[1024];   int len = 0;                            while (len = Zin.read (b))! =-1) {dout.write (b, 0, Len);                            } dout.close ();                            Fout.close ();                            Zin.closeentry ();                            if (Unziplistener! = null) {Unziplistener.onzip (myFile, Filesavepath);                }}}//File.delete ();                    } catch (IOException e) {e.printstacktrace ();                Exception = e;            } return null; }



3. Add the path to Ccfileutils->searchpath. Call through JNI

public static native void Addsearchpath (String path);


    void Java_com_xxx_base_basegameactivity_addsearchpath (jnienv*  env, jobject thiz,jstring path)    {            const Char *char_path = (env)->getstringutfchars (path, NULL);        Ccfileutils::sharedfileutils ()->addsearchpath (Char_path);            }


After the test of time, there is something wrong with this way. 1. Extract the large amount of resources into SD card which greatly consumes the user's SD cards. 2. Some resources are cleaned up by some management software as caches. 3. The decompression process will occupy the line incurring.


For this out of the second version of the directly loaded download the resources in the ZIP package. The second edition is modified on the basis of the first edition. Continue to study the Cocos resource loading mode, flip through the cocos-x source code, know how cocos through a simple name like xxxxbg.png to get the corresponding picture resources.


1. Get Xxxxbg.png's fullpath. There are two possible types of this fullpath are the absolute path in the assets in the APK, and the absolute path in the SD. FullPath = searchpath + orderpath + filename

Check CCFileUtils.cpp

->std::string ccfileutils::fullpathforfilename (const char* pszfilename)

->std::string ccfileutils::getpathforfilename (const std::string& filename, const std::string& Resolutiondirectory, const std::string& SearchPath)

->std::string ccfileutils::getfullpathfordirectoryandfilename (const std::string& strDirectory, const std:: string& strFileName)

->bool ccfileutilsandroid::isfileexist (const std::string& strFilePath)

When entering to Isfileexit know this method, jump to CCFileUtilsAndroid.cpp

Probably know how fullpathforfilename this method works, probably means that the SearchPath array + orderpath digital double-loop traversal of the fullpath of the filename, if there is a file to return to FullPath, Go to the next step to read the data. Isfileexist is the key approach we have to take a look at this method.

<pre name= "code" class= "CPP" >bool ccfileutilsandroid::isfileexist (const std::string& strFilePath) {//    The fullpath length of the stitching is 0, equal to 0 this file is marked as not having the current temporary fullpath if (0 = = Strfilepath.length ()) {return false;        } bool Bfound = FALSE;    Check whether file exists in apk. If FullPath is/begins to indicate that the path is in assets S_pzipfile point to APK assets if (strfilepath[0]! = '/') {std::string strpath = St        Rfilepath;            if (Strpath.find (m_strdefaultresrootpath)! = 0) {//didn ' t find "assets/" at the beginning of the path, adding it.        Strpath.insert (0, M_strdefaultresrootpath);        } if (S_pzipfile->fileexists (strpath)) {bfound = true;        }}//Otherwise the path of the SD card is simple to read, the pointer is either empty or exists. {FILE *FP = fopen (Strfilepath.c_str (), "R");            if (fp) {bfound = true;        Fclose (FP); }} return bfound;}


2. Use FullPath to get pictures or sounds, plist unsigned char* data.

->unsigned char* ccfileutils::getfiledata (const char* pszfilename, const char* Pszmode, unsigned long * pSize)

->unsigned char* ccfileutilsandroid::d ogetfiledata (const char* pszfilename, const char* Pszmode, unsigned long * pSize , BOOL Forasync)

unsigned char* ccfileutilsandroid::d ogetfiledata (const char* pszfilename, const char* Pszmode, unsigned long * pSize, BOOL        Forasync) {unsigned char * pData = 0; if ((! pszFileName) | | (! Pszmode) | |    0 = = strlen (pszfilename)) {return 0;        } String fullPath = Fullpathforfilename (pszFileName); If the assets path is loaded asynchronously or synchronously with the data if (fullpath[0]! = '/') {if (forasync) {pData = S_pzipfile-&gt        ; Getfiledata (Fullpath.c_str (), pSize, S_pzipfile->_datathread);        } else {pData = S_pzipfile->getfiledata (Fullpath.c_str (), pSize); }}//Simple open file read files else {do {//read Rrom Other path than user set it/            /cclog ("GETTING FILE ABSOLUTE DATA:%s", pszfilename);            FILE *FP = fopen (Fullpath.c_str (), Pszmode);                        Cc_break_if (!FP);            unsigned long size;            Fseek (Fp,0,seek_end);        Size = Ftell (FP);    Fseek (Fp,0,seek_set);            PData = new unsigned char[size];            Size = Fread (pdata,sizeof (unsigned char), SIZE,FP);                        Fclose (FP);            if (pSize) {*psize = size;    }} while (0);        } if (! PData) {std::string msg = "Get data from File (";        Msg.append (pszFileName). Append (") failed!");    Cclog ("%s", Msg.c_str ()); } return pData;}


Now that you know how to read the data on the Android side, let's think about how a file in a zip can be checked and returned to FullPath and then read the data.

Like the following path

The/res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav in/storage/emulated/0/donutabc/unitres/game_22.zip.

1. Get FullPath. Cocos get FullPath in both apk assets and SD, think of the SD card path only need to add SearchPath to find the corresponding resources, we can also add the zip file as path to SearchPath, Detects if the file exists. Let's check if the files in the zip are there or not, so we can get fullpath.

Get the following fullpath, ending with ' # ' to distinguish whether he is the SearchPath in the SD card or the SearchPath in the zip

SearchPath =/storage/emulated/0/donutabc/unitres/game_22.zip#

Orderpath + filename =/res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav

FullPath =/storage/emulated/0/donutabc/unitres/game_22.zip#/res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav


BOOL Ccfileutilsandroid::isfileexist (const std::string& strFilePath) {if (0 = = Strfilepath.length ()) {RE    Turn false;        } bool Bfound = FALSE;    Check whether file exists in apk.        if (strfilepath[0]! = '/') {std::string strpath = strFilePath;            if (Strpath.find (m_strdefaultresrootpath)! = 0) {//didn ' t find "assets/" at the beginning of the path, adding it.        Strpath.insert (0, M_strdefaultresrootpath);        } if (S_pzipfile->fileexists (strpath)) {bfound = true; }} else {//See if the path of # is using the method in the Zip method to detect the existence of the file Zlib library detects if the file exists///STORAGE/EMULATED/0/DONUTABC/UNITRES/GA        Me_22.zip#/res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav std::string pszfilename = StrFilePath;        std::string Pszzipfilepath = "";        size_t pos = strfilepath.find_last_of ("#"); if (pos! = Std::string::npos) {//cclog ("isfileexist########## #strFilePath:%s", Strfilepath.c_str ());            File_path =/storage/emulated/0/donutabc/unitres/game_22.zip Pszzipfilepath = strfilepath.substr (0, POS); File = Res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav pszFileName = strfilepath.substr (pos+2)            ;            Cclog ("isfileexist########## #zip path:file_path:%s file:%s", Pszzipfilepath.c_str (), Pszfilename.c_str ());            Unzfile pFile = NULL;                do {cc_break_if (!pszzipfilepath.c_str () | | |!pszfilename.c_str ());                Cc_break_if (strlen (pszzipfilepath.c_str ()) = = 0);                PFile = Unzopen (Pszzipfilepath.c_str ());                int nret = Unzlocatefile (PFile, Pszfilename.c_str (), 1);                Cclog ("isfileexist########## #nRet:%d", nret);                     if (UNZ_OK = = nret) {//Cclog ("isfileexist########## #UNZ_OK");                Bfound = true;  } if (PFile) {                  Unzclose (PFile);        }} while (0);            }else {FILE *FP = fopen (Strfilepath.c_str (), "R");                if (fp) {bfound = true;            Fclose (FP); }}} return bfound;}


2. Obtain resource data. Careful analysis CCFileUtils.cpp will see a method unsigned char* ccfileutils::getfiledatafromzip (const char* Pszzipfilepath, const char* pszFileName, unsigned long * pSize) Yes this method is to read the data in the zip file. Give it to the force.

Let's modify the Dogetfiledata method to read the zip data just fine ^ ^!

unsigned char* ccfileutilsandroid::d ogetfiledata (const char* pszfilename, const char* Pszmode, unsigned long * pSize, BOOL        Forasync) {unsigned char * pData = 0; if ((! pszFileName) | | (! Pszmode) | |    0 = = strlen (pszfilename)) {return 0;        } String fullPath = Fullpathforfilename (pszFileName);  if (fullpath[0]! = '/') {if (forasync) {pData = S_pzipfile->getfiledata (Fullpath.c_str (),        PSize, S_pzipfile->_datathread);        } else {pData = S_pzipfile->getfiledata (Fullpath.c_str (), pSize);             }} else {do {//Cclog ("dogetfiledata########## #strFilePath:%s", Fullpath.c_str ()); See if the path is #///storage/emulated/0/donutabc/unitres/game_22.zip#/res/pub_element/l1u1/audio/pub_unit1_blue            _audio.wav std::string pszfilenametemp = FullPath;            std::string Pszzipfilepath = "";    size_t pos = fullpath.find_last_of ("#");        if (pos! = Std::string::npos) {//File_path =/storage/emulated/0/donu                Tabc/unitres/game_22.zip Pszzipfilepath = fullpath.substr (0, POS);                File = Res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav pszfilenametemp = fullpath.substr (pos+2);                               Cclog ("Dogetfiledata path:file_path:%s file:%s", Pszzipfilepath.c_str (), Pszfilenametemp.c_str ());            PData = Getfiledatafromzip (Pszzipfilepath.c_str (), Pszfilenametemp.c_str (), pSize); }else {//Read Rrom Other path than user set it//cclog ("GETTING FILE ABSOLUTE DATA:%s", Pszfil                ENAME);                FILE *FP = fopen (Fullpath.c_str (), Pszmode);                            Cc_break_if (!FP);                unsigned long size;                Fseek (Fp,0,seek_end);                Size = Ftell (FP);                Fseek (Fp,0,seek_set); PData = new unsigned char[size];                Size = Fread (pdata,sizeof (unsigned char), SIZE,FP);                            Fclose (FP);                if (pSize) {*psize = size;        }}} while (0);        by SC Load if (pData) {pData = Resourcesdecode::shareddecode ()->decodedata (PData, *psize, pSize);        }} if (! PData) {std::string msg = "Get data from File (";        Msg.append (pszFileName). Append (") failed!");    Cclog ("%s", Msg.c_str ()); } return pData;}


Next, we simply add the downloaded zip path to the SearchPath to read the data!

Get SD card path on Android side

public static String Getsdcarddir () {        return environment.getexternalstoragedirectory (). GetPath () + "/";    }

SearchPath = SD path + download path + "#"


ccfileutils::sharedfileutils ()->addsearchpath ("/storage/emulated/0/donutabc/unitres/game_22. zip#");


Some classmates asked how to fill in the path of a picture in cocos

Of course it's the path in the zip. /res/pub_element/l1u1/audio/pub_unit1_blue_audio.wav

Open the compression pack and you'll see.


Download the full revision ↓

{{{{{{{{{{{}}}}}}}}


Cocos2d-x Android Direct load download to SD Zip resource file

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.