在Android開發中我們經常使用MediaPlayer來播放音頻文件,但是MediaPlayer存在一些不足,例如:資源占用量較高、延遲時間較長、不支持多個音頻同時播放等。這些缺點決定了MediaPlayer在某些場合的使用情況不會很理想,例如在對時間精準度要求相對較高的游戲開發中。
在游戲開發中我們經常需要播放一些游戲音效(比如:子彈爆炸,物體撞擊等),這些音效的共同特點是短促、密集、延遲程度小。在這樣的場景下,我們可以使用SoundPool代替MediaPlayer來播放這些音效。
SoundPool(android.media.SoundPool),顧名思義是聲音池的意思,主要用于播放一些較短的聲音片段,支持從程序的資源或文件系統加載。與MediaPlayer相比,SoundPool的優勢在于CPU資源占用量低和反應延遲小。另外,SoundPool還支持自行設置聲音的品質、音量、播放比率等參數,支持通過ID對多個音頻流進行管理。
就現在已知的資料來說,SoundPool有一些設計上的BUG,從固件版本1.0開始有些還沒有修復,我們在使用中應該小心再小心。相信將來Google會修復這些問題,但我們最好還是列出來:
1. SoundPool最大只能申請1M的內存空間,這就意味著我們只能用一些很短的聲音片段,而不是用它來播放歌曲或者做游戲背景音樂。
2. SoundPool提供了pause和stop方法,但這些方法建議最好不要輕易使用,因為有些時候它們可能會使你的程序莫名其妙的終止。建議使用這兩個方法的時候盡可能多做測試工作,還有些朋友反映它們不會立即中止播放聲音,而是把緩沖區里的數據播放完才會停下來,也許會多播放一秒鐘。
3. SoundPool的效率問題。其實SoundPool的效率在這些播放類中算是很好的了,但是有的朋友在G1中測試它還是有100ms左右的延遲,這可能會影響用戶體驗。也許這不能管SoundPool本身,因為到了性能比較好的Droid中這個延遲就可以讓人接受了。
在現階段SoundPool有這些缺陷,但也有著它不可替代的優點,基于這些我們建議大在如下情況中多使用SoundPool:1.應用程序中的聲效(按鍵提示音,消息等)2.游戲中密集而短暫的聲音(如多個飛船同時爆炸)
1.相關方法介紹:
1)構造方法:
SoundPool(int maxStreams, int streamType, int srcQuality) 參數依次是:
①指定支持多少個聲音,SoundPool對象中允許同時存在的最大流的數量。
②指定聲音類型,流類型可以分為STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING,STREAM_MUSIC 和 STREAM_ALARM四種類型。在AudioManager中定義。
③指定聲音品質(采樣率變換質量),一般直接設置為0!
在低版本中可以用上述構造方法,而API 21(Android 5.0)后這個構造方法就過時了! 而用到一個SoundPool.Builder的東東,我們要實例化SoundPool只需調用:
SoundPool.Builder spb = new SoundPool.Builder();spb.setMaxStreams(10);spb.setAudioAttributes(null); //轉換音頻格式SoundPool sp = spb.build(); //創建SoundPool對象
要使用上述代碼的話,TargetSDK版本要設置大于等于21哦!而且如果minSDK版本小于21 會出現下面的提醒:

2)常用方法介紹:
①加載聲音資源:
參數介紹:
AssetFileDescriptor descriptor = assetManager.openFd("biaobiao.mp3");②播放控制:
play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
參數依次是:
③資源釋放:
可以調用release()方法釋放所有SoundPool對象占據的內存和資源,當然也可以根據聲音 ID來釋放!
3.使用代碼示例:
運行效果圖:

當點擊按鈕的時候會,"Duang"一下,這里演示了兩種load的方法,分別是raw和assests!
關鍵代碼:
MainActivity.java:
private void initSP() throws Exception{ //設置最多可容納5個音頻流,音頻的品質為5 mSoundPool = new SoundPool(5, AudioManager.STREAM_SYSTEM, 5); soundID.put(1, mSoundPool.load(this, R.raw.duang, 1)); soundID.put(2 , mSoundPool.load(getAssets().openFd("biaobiao.mp3") , 1)); //需要捕獲IO異常 soundID.put(3, mSoundPool.load(this, R.raw.duang, 1)); soundID.put(4, mSoundPool.load(this, R.raw.duang, 1)); soundID.put(5, mSoundPool.load(this, R.raw.duang, 1)); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_play1: mSoundPool.play(soundID.get(1), 1, 1, 0, 0, 1); break; case R.id.btn_play2: mSoundPool.play(soundID.get(2), 1, 1, 0, 0, 1); break; case R.id.btn_play3: mSoundPool.play(soundID.get(3), 1, 1, 0, 0, 1); break; case R.id.btn_play4: mSoundPool.play(soundID.get(4), 1, 1, 0, 0, 1); break; case R.id.btn_play5: mSoundPool.play(soundID.get(5), 1, 1, 0, 0, 1); break; case R.id.btn_release: mSoundPool.release(); //回收SoundPool資源 break; }代碼非常簡單,另外如果你點擊了最后一個按鈕的話,SoundPool就會被釋放,然后再其他按鈕 就不會Duang了哦~
4.OnLoadCompleteListener監聽聲音文件是否加載完畢
嗯,這個是臨時想起的,寫完在寫另一篇的時候突然想起,用法也很簡單,我們可以 往上面的代碼中添加OnLoadCompleteListener這個東東,然后重寫onLoadComplete()方法 ,最后為SoundPool對象設置這個東東即可!
mSoundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { @Override public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { Toast.makeText(MainActivity.this,"加特技準備完畢~",Toast.LENGTH_SHORT).show(); }});以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答