在 Android 2.2+ 上,有一个名为SoundPool.OnLoadCompleteListener的东西,它允许知道声音是否已成功加载。
我的目标是较低的 API 版本(最好是 1.6,但可以使用 2.1),我需要知道声音是否已正确加载(因为它是由用户选择的)。正确的方法是什么?
我希望不要使用 MediaPlayer 加载声音一次,如果使用 SoundPool 正确?!
在 Android 2.2+ 上,有一个名为SoundPool.OnLoadCompleteListener的东西,它允许知道声音是否已成功加载。
我的目标是较低的 API 版本(最好是 1.6,但可以使用 2.1),我需要知道声音是否已正确加载(因为它是由用户选择的)。正确的方法是什么?
我希望不要使用 MediaPlayer 加载声音一次,如果使用 SoundPool 正确?!
OnLoadCompleteListener
我实现了一种至少适用于 Android 2.1的兼容类。
构造函数接受一个SoundPool
对象,并且SoundPool.load(..)
调用了 的声音必须用 注册OnLoadCompleteListener.addSound(soundId)
。在此之后,听众会定期尝试播放请求的声音(以零音量)。如果成功,它会调用你的实现onLoadComplete
,就像在 Android 2.2+ 版本中一样。
这是一个使用示例:
SoundPool mySoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
OnLoadCompleteListener completionListener = new OnLoadCompleteListener(mySoundPool) {
@Override
public void onLoadComplete(SoundPool soundPool, int soundId, int status) {
Log.i("OnLoadCompleteListener","Sound "+soundId+" loaded.");
}
}
int soundId=mySoundPool.load(this, R.raw.funnyvoice,1);
completionListener.addSound(soundId); // tell the listener to test for this sound.
这是来源:
abstract class OnLoadCompleteListener {
final int testPeriodMs = 100; // period between tests in ms
/**
* OnLoadCompleteListener fallback implementation for Android versions before 2.2.
* After using: int soundId=SoundPool.load(..), call OnLoadCompleteListener.listenFor(soundId)
* to periodically test sound load completion. If a sound is playable, onLoadComplete is called.
*
* @param soundPool The SoundPool in which you loaded the sounds.
*/
public OnLoadCompleteListener(SoundPool soundPool) {
testSoundPool = soundPool;
}
/**
* Method called when determined that a soundpool sound has been loaded.
*
* @param soundPool The soundpool that was given to the constructor of this OnLoadCompleteListener
* @param soundId The soundId of the sound that loaded
* @param status Status value for forward compatibility. Always 0.
*/
public abstract void onLoadComplete(SoundPool soundPool, int soundId, int status); // implement yourself
/**
* Method to add sounds for which a test is required. Assumes that SoundPool.load(soundId,...) has been called.
*
* @param soundPool The SoundPool in which you loaded the sounds.
*/
public void addSound(int soundId) {
boolean isFirstOne;
synchronized (this) {
mySoundIds.add(soundId);
isFirstOne = (mySoundIds.size()==1);
}
if (isFirstOne) {
// first sound, start timer
testTimer = new Timer();
TimerTask task = new TimerTask() { // import java.util.TimerTask for this
@Override
public void run() {
testCompletions();
}
};
testTimer.scheduleAtFixedRate(task , 0, testPeriodMs);
}
}
private ArrayList<Integer> mySoundIds = new ArrayList<Integer>();
private Timer testTimer; // import java.util.Timer for this
private SoundPool testSoundPool;
private synchronized void testCompletions() {
ArrayList<Integer> completedOnes = new ArrayList<Integer>();
for (Integer soundId: mySoundIds) {
int streamId = testSoundPool.play(soundId, 0, 0, 0, 0, 1.0f);
if (streamId>0) { // successful
testSoundPool.stop(streamId);
onLoadComplete(testSoundPool, soundId, 0);
completedOnes.add(soundId);
}
}
mySoundIds.removeAll(completedOnes);
if (mySoundIds.size()==0) {
testTimer.cancel();
testTimer.purge();
}
}
}
SoundPool 确实异步加载文件。不幸的是,在 API8 级别之前,没有 API 可以检查加载是否已完成。
正如您所说,从 Android API8 开始,可以通过 OnLoadCompleteListener 检查加载是否完成。这是一个小例子:Android 声音教程。