2014年9月4日 星期四

cocos2d-x 读取android手机sd卡中的资源(android http下载zip资源、解压)

http://blog.csdn.net/lnslc/article/details/8789531


 cocos2d-x版本 2.0.4
   cocos2d-x做android游戏在线更新资源。
   费话不多说,直接上代码:
   下载和解压是用android端java实现:

[java] view plaincopy
  1. /** 
  2.      *  
  3.      * @return 
  4.      * 100 没有sd卡 
  5.      * 1   下载过程中出错 
  6.      * 2   解压过程中出错 
  7.      * 3   删除过程中出错 
  8.      */  
  9.     public static int download()  
  10.     {  
  11.         //检查sd卡  
  12.         if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))  
  13.         {  
  14.             return 100;  
  15.         }  
  16.         //下载保存  
  17.         try  
  18.         {  
  19.             saveToFile("http://192.168.0.14/data/Data.zip", Environment.getExternalStorageDirectory()+"/data.zip");  
  20.         }  
  21.         catch (IOException e)  
  22.         {  
  23.             e.printStackTrace();  
  24.             return 1;  
  25.         }  
  26.           
  27.         //解压  
  28.         File zipFile = new File(Environment.getExternalStorageDirectory()+"/data.zip");  
  29.         try  
  30.         {  
  31.             upZipFile(zipFile,Environment.getExternalStorageDirectory()+"/xydata/data/");  
  32.         }  
  33.         catch (ZipException e)  
  34.         {  
  35.             e.printStackTrace();  
  36.             return 2;  
  37.         }  
  38.         catch (IOException e)  
  39.         {  
  40.             e.printStackTrace();  
  41.             return 2;  
  42.         }  
  43.         //删除zip  
  44.         try  
  45.         {  
  46.             deleteFile(zipFile);  
  47.         }  
  48.         catch(Exception e)  
  49.         {  
  50.             e.printStackTrace();  
  51.             return 3;  
  52.         }  
  53.         return 0;  
  54.     }  
  55.       
  56.       
  57.     private static int BUFFER_SIZE = 8096//缓冲区大小  
  58.     /** 
  59.      * 将HTTP资源另存为文件 
  60.      * 
  61.      * @param destUrl String 
  62.      * @param fileName String 
  63.      * @throws Exception 
  64.      */  
  65.     public static void saveToFile(String destUrl, String fileName) throws IOException  
  66.     {  
  67.         FileOutputStream fos = null;  
  68.         BufferedInputStream bis = null;  
  69.         HttpURLConnection httpUrl = null;  
  70.         URL url = null;  
  71.         byte[] buf = new byte[BUFFER_SIZE];  
  72.         int size = 0;  
  73.   
  74.         // 建立链接  
  75.         url = new URL(destUrl);  
  76.         httpUrl = (HttpURLConnection) url.openConnection();  
  77.         // 连接指定的资源  
  78.         httpUrl.connect();  
  79.         // 获取网络输入流  
  80.         bis = new BufferedInputStream(httpUrl.getInputStream());  
  81.         // 建立文件  
  82.         fos = new FileOutputStream(fileName);  
  83.   
  84.         System.out.println("正在获取链接[" + destUrl + "]的内容...\n将其保存为文件[" + fileName + "]");  
  85.         // 保存文件  
  86.         while ((size = bis.read(buf)) != -1)  
  87.         {  
  88.             fos.write(buf, 0, size);  
  89.         }  
  90.         fos.close();  
  91.         bis.close();  
  92.         httpUrl.disconnect();  
  93.     }  
  94.       
  95.     /**  
  96.      * 解压缩一个文件  
  97.      *  
  98.      * @param zipFile 要解压的压缩文件  
  99.      * @param folderPath 解压缩的目标目录  
  100.      * @throws IOException 当解压缩过程出错时抛出  
  101.  */  
  102.     public static void upZipFile(File zipFile, String folderPath) throws ZipException, IOException  
  103.     {  
  104.         File desDir = new File(folderPath);  
  105.         if (!desDir.exists())  
  106.         {  
  107.             desDir.mkdirs();  
  108.         }  
  109.   
  110.         ZipFile zf = new ZipFile(zipFile);  
  111.         for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();)  
  112.         {  
  113.             ZipEntry entry = ((ZipEntry) entries.nextElement());  
  114.             InputStream in = zf.getInputStream(entry);  
  115.             String str = folderPath + File.separator + entry.getName();  
  116.             str = new String(str.getBytes("8859_1"), "GB2312");  
  117.             File desFile = new File(str);  
  118.             if (!desFile.exists())  
  119.             {  
  120.                 File fileParentDir = desFile.getParentFile();  
  121.                 if (!fileParentDir.exists())  
  122.                 {  
  123.                     fileParentDir.mkdirs();  
  124.                 }  
  125.                 desFile.createNewFile();  
  126.             }  
  127.             OutputStream out = new FileOutputStream(desFile);  
  128.             byte buffer[] = new byte[1024];  
  129.             int realLength;  
  130.             while ((realLength = in.read(buffer)) > 0)  
  131.             {  
  132.                 out.write(buffer, 0, realLength);  
  133.             }  
  134.             in.close();  
  135.             out.close();  
  136.         }  
  137.     }  
  138.       
  139.     //将SD卡文件删除  
  140.     public static void deleteFile(File file)  
  141.     {  
  142.         if (file.exists())  
  143.         {  
  144.             if (file.isFile())  
  145.             {  
  146.                 file.delete();  
  147.             }  
  148.             // 如果它是一个目录  
  149.             else if (file.isDirectory())  
  150.             {  
  151.                 // 声明目录下所有的文件 files[];  
  152.                 File files[] = file.listFiles();  
  153.                 for (int i = 0; i < files.length; i++)  
  154.                 { // 遍历目录下所有的文件  
  155.                     deleteFile(files[i]); // 把每个文件 用这个方法进行迭代  
  156.                 }  
  157.             }  
  158.             file.delete();  
  159.         }  
  160.     }  
  161.       



   流程就是先把zip包下载到sd卡中,再解压到指定目录,解压完成后zip就没了删之。
    在c++里检测版本,在需要更新时通过jni调用download()方法,这里的方法都写成static的,纯是为了jni调用时省点事。
    要是不会用通过jni在c++和java之间相互调用可以度娘、google,也可以参考cocos2dx\platform\android\jni目录下Java开头的几个类和samples\HelloCpp\proj.android\src\org\cocos2dx\lib里边的java文件结合着看看就明白了。
还要在AndroidManifest.xml中加sd卡中写文件和访问网络的权限如下:
[java] view plaincopy
  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>   
  2. <uses-permission android:name="android.permission.INTERNET"/>  


现在sd卡的资源有了,下面解决调用问题,方法有2也直接上代码:

  1. //方法1  
  2. unsigned long filesize;  
  3.     CCImage image;  
  4.     char* buffer = (char *)CCFileUtils::sharedFileUtils()->getFileData("/mnt/sdcard/to3/icon.png""rb", &filesize);  
  5.   
  6.     if(image.initWithImageData((void*)buffer, filesize, CCImage::kFmtPng))  
  7.     {  
  8.         CCTexture2D *texture = new CCTexture2D();  
  9.         texture->initWithImage(&image);  
  10.   
  11.         if( texture )   
  12.         {  
  13.             CCSprite *sprite = CCSprite::createWithTexture(texture);  
  14.             if (sprite)  
  15.             {  
  16.                 CCLog("111sprite != null");  
  17.                 this->addChild(sprite);  
  18.                 sprite->setPosition(ccp(200, 100));  
  19.             }  
  20.             else  
  21.             {  
  22.                 CCLog("111sprite == null");  
  23.             }  
  24.         }  
  25.     }  
  26. //方法2  
  27.     bool flag = image.initWithImageFile("/mnt/sdcard/to3/icon.png", CCImage::kFmtPng);  
  28.     if (flag)  
  29.     {  
  30.         CCTexture2D *texture2D = new CCTexture2D();  
  31.         texture2D->initWithImage(&image);  
  32.         CCSprite *sprite = CCSprite::createWithTexture(texture2D);  
  33.         if (sprite)  
  34.         {  
  35.             CCLog("222sprite != null");  
  36.             this->addChild(sprite);  
  37.             sprite->setPosition(ccp(100, 100));  
  38.         }  
  39.         else  
  40.         {  
  41.             CCLog("222sprite == null");  
  42.         }  
  43.     }  



方法1不只可以读图片,其他的 xml之类的文件也可以读,方法2只是读图片的。
/mnt/sdcard是sd卡的根目录,这里用于测试是写死的,由于手机厂商不同,这个路径也会不同,要通过jni(又是jni)获取Environment.getExternalStorageDirectory()
附图一张,图中的两小人就是上面的两个方法加进去的。



就到这里吧

有什么不对的地方请指正,谢谢!