一、使用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 } }