一、使用MediaPlayer來播放音頻文件存在一些不足:
例如:資源佔用量較高、延遲時間較長、不支持多個音頻同時播放等。
這些缺點決定了MediaPlayer在某些場合的使用情況不會很理想,所有,一般的遊戲開發都是用的Soundpool。
在沒有了解Soundpool之前,我也是使用的普通的MediaPlayer進行文件播放,但這個方法不適合用於遊戲開發,因爲遊戲裏面經常要同時播放幾個音樂文件,用過MediaPlayer的朋友都該知道,它是不支持實時播放多個聲音的,而且還會出現或多或少的延遲,尤其是在快速連續播放聲音(比如連續猛點按鈕)時,會非常明顯,長的時候會出現3~5秒的延遲,【使用MediaPlayer.seekTo() 這個方法來解決此問題】;
相對於使用SoundPool存在的一些問題:
1. SoundPool是爲播放小文件而存在的。一般限定Soundpool播放文件的大小爲1M。
2. SoundPool提供了pause和stop方法,但這些方法建議最好不要輕易使用,因爲有些時候它們可能會使你的程序莫名其妙的終止。還有些朋友反映它們不會立即中止播放聲音,而是把緩衝區裏的數據播放完纔會停下來,也許會多播放一秒鐘。
3. 音頻格式建議使用OGG格式。使用WAV格式的音頻文件存放遊戲音效,經過反覆測試,在音效播放間隔較短的情況下會出現異常關閉的情況(有說法是SoundPool目前只對16bit的WAV文件有較好的支持)。後來將文件轉成OGG格式,問題得到了解決。
4.在使用SoundPool播放音頻的時候,如果在初始化中就調用播放函數進行播放音樂那麼根本沒有聲音,不是因爲沒有執行,而是SoundPool需要一準備時間!這就是剛剛我們說的用OnLoadCompleteListener來解決的問題。如果你非得是1.6甚至更低的話,那建議在播放的時候,將play放到一個點擊事件中去,當然在這個中也要注意一下兩點。
a、 別忘記綁定操作! mp.setOnCompletionListener(this);
b、如果你設置了循環播放 mp.setLooping(true); 的話,那麼永遠都不會監聽到播放完成的狀態!!
二、SoundPool
SoundPool
構造方法
構造方法 |
描述 |
public SoundPool (int maxStreams, int streamType, int srcQuality)
|
參數說明: maxStreams:指定支持多少個文件 streamType:指定聲音類型 srcQuality:聲音品質 |
常見方法
方法名稱 |
描述 |
public int load (Context context, int resId, int priority) |
從資源ID所對應的資源加載聲音 |
public int load (AssetFileDescriptor afd, int priority) |
從原始資源文件中加載聲音 |
public int load (FileDescriptor fd, long offset, long length, int priority) |
從原始資源文件中加載聲音並設置加載從哪開始到多長的聲音文件 |
public int load (String path, int priority) |
從指定文件路徑加載聲音 |
public final void pause (int streamID) |
暫停 |
public final int play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) |
播放 參數說明: soundID:資源ID leftVolume:左頻道聲音 rightVolume:右頻道聲音 loop:-1代表循環,0代表不循環 rate:值0.5-2.0設置1爲正常 |
public final void release () |
釋放SoundPool對象資源 |
public final void stop (int streamID) |
停止 |
public void setOnLoadCompleteListener (SoundPool.OnLoadCompleteListener listener) |
設置監聽器,在加載音樂文件完成時觸發該事件 |
三、上代碼:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
android:orientation="vertical" >
<Button
android:id="@+id/bt"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
SoundPoolActivity.java
import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class SoundPoolActivity extends Activity implements
SoundPool.OnLoadCompleteListener{
/** Called when the activity is first created. */
private Button button;
private int[] menuSound;
private SoundPool mSoundPool = null;
private int i =0;
// private final Handler mHandler = new MyHandler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.bt);
mSoundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 0);
mSoundPool.setOnLoadCompleteListener(ViewgroupActivity.this);
menuSound = new int[2];
mSoundPool = new SoundPool(2, AudioManager.STREAM_SYSTEM, 0);
menuSound[0] = mSoundPool.load(getApplicationContext(),
R.raw.eng_music, 1);
menuSound[1] = mSoundPool.load(getApplicationContext(),
R.raw.eng_music, 1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if((i%2)==0){
i++;
mSoundPool.play(menuSound[0], 10, 10, 0, 0, (float) 1);// 播放鈴聲
}else {
mSoundPool.play(menuSound[1], 10, 10, 0, 0, (float) 1);// 播放鈴聲
}
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
mSoundPool.release();
mSoundPool.stop(menuSound[0]);
mSoundPool.stop(menuSound[1]);
super.onDestroy();
}
@Override
public void onLoadComplete(SoundPool arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
}