5

在 Android 2.2+ 上,有一个名为SoundPool.OnLoadCompleteListener的东西,它允许知道声音是否已成功加载。

我的目标是较低的 API 版本(最好是 1.6,但可以使用 2.1),我需要知道声音是否已正确加载(因为它是由用户选择的)。正确的方法是什么?

我希望不要使用 MediaPlayer 加载声音一次,如果使用 SoundPool 正确?!

4

2 回答 2

10

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();
        }
    }
}
于 2011-08-14T22:43:19.680 回答
1

SoundPool 确实异步加载文件。不幸的是,在 API8 级别之前,没有 API 可以检查加载是否已完成。

正如您所说,从 Android API8 开始,可以通过 OnLoadCompleteListener 检查加载是否完成。这是一个小例子:Android 声音教程

于 2011-06-16T07:58:47.510 回答