cocos2d-x android 直接加载下载到sd的zip里的资源文件(二)

cocos2d-x android 直接加载下载到sd的zip里的资源文件(二),第1张

概述上一节 解决了读文件的问题,游戏也跑起来了,可是音效和背景音乐,死活播放不出来。回想一下,的确没有考虑到游戏的音效问题。让我们再折腾一下,播放zip里的音效问题。cocos-x 安卓的背景音乐处理交给了Cocos2dxMusic.java,音效处理交给了Cocos2dxSound.java。别的我们不看,就关注声音资源加载的地方。 先分析一下Cocos2dxMusic.java 的声音资源加载方法

上一节 解决了读文件的问题,游戏也跑起来了,可是音效和背景音乐,死活播放不出来。回想一下,的确没有考虑到游戏的音效问题。让我们再折腾一下,播放zip里的音效问题。cocos-x 安卓的背景音乐处理交给了Cocos2dxMusic.java,音效处理交给了Cocos2dxSound.java。别的我们不看,就关注声音资源加载的地方。

先分析一下Cocos2dxMusic.java 的声音资源加载方法

private MediaPlayer createMediaplayer(final String pPath) ;

这个方法就是啦。大概就是判断fullpath路径是否 '/'开头,如果是就加载sd卡声音资源,否则加载apk里的资源。


/**	 * create mediaplayer for music	 * 	 * @param pPath	 *            the pPath relative to assets	 * @return	 */	private MediaPlayer createMediaplayer(final String pPath) {		MediaPlayer mediaPlayer = new MediaPlayer();		try {			//加载sd卡里的声音资源			if (pPath.startsWith("/")) {				final fileinputStream fis = new fileinputStream(pPath);				mediaPlayer.setDataSource(fis.getFD());				fis.close();			} else {				//加载apk里的声音资源				final AssetfileDescriptor assetfileDescritor = this.mContext.getAssets().openFd(pPath);				mediaPlayer.setDataSource(assetfileDescritor.getfileDescriptor(),assetfileDescritor.getStartOffset(),assetfileDescritor.getLength());			}			mediaPlayer.prepare();			mediaPlayer.setVolume(this.mleftVolume,this.mRightVolume);		} catch (final Exception e) {			mediaPlayer = null;			Log.e(Cocos2dxMusic.TAG,"error: " + e.getMessage(),e);		}		return mediaPlayer;	}

在分析一下Cocos2dxSound.java的声音资源加载方法

->public int playEffect(final String pPath,final boolean pLoop)

->public int preloadEffect(final String pPath)

->public int createSoundIDFromAsset(final String pPath)

也是是判断fullpath路径是否 '/'开头,如果是就加载sd卡声音资源,否则加载apk里的资源。


	public int createSoundIDFromAsset(final String pPath) {		int soundID = Cocos2dxSound.INVALID_SOUND_ID;		try {			if (pPath.startsWith("/")) {				//加载sd卡声音资源				soundID = this.mSoundPool.load(pPath,0);			} else {				//加载apk里的声音资源				soundID = this.mSoundPool.load(this.mContext.getAssets().openFd(pPath),0);			}		} catch (final Exception e) {			soundID = Cocos2dxSound.INVALID_SOUND_ID;			Log.e(Cocos2dxSound.TAG,e);		}		// mSoundPool.load returns 0 if something goes wrong,for example a file does not exist		if (soundID == 0) {			soundID = Cocos2dxSound.INVALID_SOUND_ID;		}		return soundID;	}	

回想起来,我们已经有fullpath ,我们要像读取向下面的资源

fullpath = /storage/emulated/0/DonutABC/unitRes/game_22.zip#/res/pub_element/L1U1/audio/pub_unit1_blue_audio.wav


有两种方法:

方法1:直接读取zip里的声音流 让播放器们播放

inputStream 这样的东西java 程序猿们太熟悉不过了,何况是ZipinputStream。我们先将对应的文件用ZipinputStream 读出,然后直接让MediaPlayer 或SoundPool 加载播放流不就可以了吗?可是童话都是骗人的。突然想起邓超演的《美人鱼》,我实在是想不通。好好的白富美在身边不要,偏偏去要一条上半身是人,下半身是鱼的人鱼。没有接口下半辈子能幸福吗!!!实在是想不通。在这个问题上,也是遇到了这样的人鱼。MediaPlayer 和 SoundPool 都没有直接播放流的方法 ,MediaPlayer的setDataSource方法。SoundPool的load方法 都没有播放流的接口。下半辈子不幸福,感觉不会再爱了。好吧换第二个方法

方法2:将zip对应的声音文件临时解压到sd卡里, 然后返回fullpath给Cocos2dxMusic.java或Cocos2dxSound.java 的加载方法。

新欢没有接口,我们找旧爱。旧爱的接口就是要个声音文件的fullpath吗,太容易满足了。让我们动手改改

Cocos2dxMusic.java 的 createMediaplayer

	/**	 * create mediaplayer for music	 *	 * @param pPath	 *            the pPath relative to assets	 * @return	 */	private MediaPlayer createMediaplayer(final String pPath) {		MediaPlayer mediaPlayer = new MediaPlayer();		try {			if (pPath.startsWith("/")) {//改了这里				String ppPath = PathUtils.getZipfilePath(pPath);				final fileinputStream fis = new fileinputStream(ppPath);				mediaPlayer.setDataSource(fis.getFD());				fis.close();			} else {				final AssetfileDescriptor assetfileDescritor = this.mContext.getAssets().openFd(pPath);				mediaPlayer.setDataSource(assetfileDescritor.getfileDescriptor(),e);		}		return mediaPlayer;	}

Cocos2dxSound.java 的createSoundIDFromAsset
public int createSoundIDFromAsset(final String pPath) {		int soundID = Cocos2dxSound.INVALID_SOUND_ID;		try {			if (pPath.startsWith("/")) {//改了下面的				String ppPath = PathUtils.getZipfilePath(pPath);				soundID = this.mSoundPool.load(ppPath,0);			} else {				soundID = this.mSoundPool.load(this.mContext.getAssets().openFd(pPath),for example a file does not exist		if (soundID == 0) {			soundID = Cocos2dxSound.INVALID_SOUND_ID;		}		return soundID;	}


解压的方法getZipfilePath

	/***	 * 获得路径 也许是zip里面的的路径	 * @param pPath	 * @return	 * @throws ZipException	 * @throws IOException     */	public static String getZipfilePath(String pPath) throws ZipException,IOException {		String zipfilepath = "";		String filename = "";		int index = pPath.indexOf("#");		String ppPath = pPath;		//是否在zip里		if(index != -1){			zipfilepath = pPath.substring(0,index);			filename = pPath.substring(index+2);			Log.d("RecordManager","zipfilepath:"+ zipfilepath + "--filename:" + filename);			String filesavename = filename.replaceAll("/","_");			ppPath = PathUtils.getTempPath() +filesavename+".temp";			file filetemp = new file(ppPath);			//是否有临时解压文件 避免重复解压			if(!filetemp.exists()){				filetemp.createNewfile();				Zipfile file = new Zipfile(zipfilepath);				fileheader fileheader = file.getfileheader(filename);				net.lingala.zip4j.io.ZipinputStream zipinputStream =  file.getinputStream(fileheader);				fileOutputStream fo =  new fileOutputStream(ppPath);				byte[] b = new byte[4096];				int readline = -1;				while ((readline = zipinputStream.read(b)) != -1) {					fo.write(b,readline);				}				fo.close();				zipinputStream.close();			}		}		return ppPath;	}

注:我用了开源的zip *** 作库 zip4j ,我git上有提交 。

好啦。我们这就跑起来。欧啦!声音出来了。这个方案凑合着用,如有更高明的方法,请回复我。


解压方法 c++版


static std::string getZipfilePath(const std::string& fullPath,const std::string& saveDir);static unsigned char* getfileDataFromZip(const char* pszZipfilePath,const char* pszfilename,unsigned long * pSize);

#include "support/zip_support/ZipUtils.h"#include "platform/CCCommon.h"#include "support/zip_support/unzip.h"#include "platform/CCfileUtils.h"


/** * fullpath 音效的绝对路径 * saveDir  解压到的地方 * return  解压后的资源返回的路径 **/std::string JNItools::getZipfilePath(const std::string& fullPath,const std::string& saveDir){    unsigned char * pBuffer = NulL;    unsigned long pSize = 0;    std::string savepath = fullPath;    std::string pszfilenameTemp = "";    std::string pszZipfilePath = "";
    size_t pos = fullPath.find_last_of("#");    if (pos != std::string::npos)    {                    // file_path = /storage/emulated/0/DonutABC/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("pszZipfilePath:%s,pszfilenameTemp:%s",pszZipfilePath.c_str(),pszfilenameTemp.c_str());                //替换‘/'        std::string filename = pszfilenameTemp;        std::string old_value = "/";        std::string new_value = "_";                for(string::size_type   pos(0);   pos!=string::npos;   pos+=new_value.length()){            if((pos=filename.find(old_value,pos))!=string::npos)                filename.replace(pos,old_value.length(),new_value);            else                break;        }//        cclOG("filename:%s",filename.c_str());                savepath =  saveDir + filename + ".temp";               const char* output = savepath.c_str();        cclOG("filename:%s",output);                   //文件如果存在就不解压了        int i = access(savepath.c_str(),0);        cclOG("filename:%d",i);                if( i == -1){            pBuffer = JNItools::getfileDataFromZip(pszZipfilePath.c_str(),pszfilenameTemp.c_str(),&pSize);                                     file *savefile = fopen(output,"wb");            fwrite(pBuffer,1,(size_t)pSize,savefile);            fflush(savefile);            fclose(savefile);                        delete pBuffer;        }                                            }        return savepath;    }/** * 解压zip 获得资源数据 **/unsigned char* JNItools::getfileDataFromZip(const char* pszZipfilePath,unsigned long * pSize){    unsigned char * pBuffer = NulL;    unzfile pfile = NulL;    *pSize = 0;        do    {//        cclOG("1");        CC_BREAK_IF(!pszZipfilePath || !pszfilename);//         cclOG("11");        CC_BREAK_IF(strlen(pszZipfilePath) == 0);//         cclOG("1111");        pfile = unzOpen(pszZipfilePath);        CC_BREAK_IF(!pfile);//         cclOG("2");        int nRet = unzLocatefile(pfile,pszfilename,1);        CC_BREAK_IF(UNZ_OK != nRet);//         cclOG("3");        char szfilePathA[260];        unz_file_info fileInfo;        nRet = unzGetCurrentfileInfo(pfile,&fileInfo,szfilePathA,sizeof(szfilePathA),NulL,0);        CC_BREAK_IF(UNZ_OK != nRet);//         cclOG("4");        nRet = unzOpenCurrentfile(pfile);        CC_BREAK_IF(UNZ_OK != nRet);//         cclOG("5");        pBuffer = new unsigned char[fileInfo.uncompressed_size];        int CC_UNUSED nSize = unzReadCurrentfile(pfile,pBuffer,fileInfo.uncompressed_size);        CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size,"the file size is wrong");//         cclOG("6");        *pSize = fileInfo.uncompressed_size;        unzCloseCurrentfile(pfile);    } while (0);        if (pfile)    {        unzClose(pfile);    }        return pBuffer;}


调方法

public static native  String getZipfilePath(String pPath,String saveDir);

    /**     * jni 调用     */    Jstring Java_org_cocos2dx_lib_PathUtils_getZipfilePath(jnienv*  env,jobject thiz,Jstring path,Jstring savedir)    {//         cclOG("filename:%s","Java_org_cocos2dx_lib_PathUtils_getZipfilePath");        std::string char_path = JniHelper::Jstring2string(path);        std::string char_savedir = JniHelper::Jstring2string(savedir);        std::string str_path = JNItools::getZipfilePath(char_path,char_savedir);//         cclOG("----getPath:%s",str_path.c_str());        env->DeleteLocalRef(path);        env->DeleteLocalRef(savedir);        return (env)->NewStringUTF(str_path.c_str());            }


Cocos2dSound.java 修改的地方
public int createSoundIDFromAsset(final String pPath) {		int soundID = Cocos2dxSound.INVALID_SOUND_ID;		try {			if (pPath.startsWith("/")) {				String ppPath = PathUtils.getZipfilePath(pPath,PathUtils.getTempPath());				soundID = this.mSoundPool.load(ppPath,for example a file does not exist		if (soundID == 0) {			soundID = Cocos2dxSound.INVALID_SOUND_ID;		}		return soundID;	}	

Cocos2dxMusic.java 修改

	/**	 * create mediaplayer for music	 *	 * @param pPath	 *            the pPath relative to assets	 * @return	 */	private MediaPlayer createMediaplayer(final String pPath) {		MediaPlayer mediaPlayer = new MediaPlayer();		try {			if (pPath.startsWith("/")) {				String ppPath = PathUtils.getZipfilePath(pPath,PathUtils.getTempPath());				final fileinputStream fis = new fileinputStream(ppPath);				mediaPlayer.setDataSource(fis.getFD());				fis.close();			} else {				final AssetfileDescriptor assetfileDescritor = this.mContext.getAssets().openFd(pPath);				mediaPlayer.setDataSource(assetfileDescritor.getfileDescriptor(),e);		}		return mediaPlayer;	}


整体来看效率没什么提高,就是不用zip4j 解压了。


还是老样子。下载完整的改动

{{{{{{{{{github传送门}}}}}}}}

本文出处

http://www.jb51.cc/article/p-wywfhxbf-bbs.html

总结

以上是内存溢出为你收集整理的cocos2d-x android 直接加载下载到sd的zip里的资源文件(二)全部内容,希望文章能够帮你解决cocos2d-x android 直接加载下载到sd的zip里的资源文件(二)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1080054.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存