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