了解在 Android 1.6/2.0/2.1 上使用 SoundPool 加载声音是否成功

发布于 2024-10-11 17:46:44 字数 328 浏览 5 评论 0原文

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

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

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

On Android 2.2+ there is something called SoundPool.OnLoadCompleteListener allowing to know whether a sound has been loaded successfully or not.

I am targeting lower API version (ideally 1.6 but could go for 2.1) and I need to know whether a sound has been loaded correctly (as it is selected by the user). What's the proper way to do it?

I hope not load the sound once with MediaPlayer and if correct with SoundPool?!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叹沉浮 2024-10-18 17:46:44

我实现了一种至少适用于 Android 2.1 的兼容 OnLoadCompleteListener 类。

构造函数采用 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();
        }
    }
}

I implemented a kind-of-compatible OnLoadCompleteListener class that works at least for Android 2.1.

The constructor takes a SoundPool object, and sounds for which the SoundPool.load(..) has been called must be registered with OnLoadCompleteListener.addSound(soundId). After this, the listener periodically attempts to play the requested sounds (at zero volume). If successful, it calls your implementation of onLoadComplete, like in the Android 2.2+ version.

Here's a usage example:

    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.

And here's the source:

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();
        }
    }
}
-残月青衣踏尘吟 2024-10-18 17:46:44

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

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

SoundPool does load the file asynchronously. Before API8 level there is unfortunately no API to check if the loading has been completely.

As you said as of Android API8 it is possible to check if the loading complete via a OnLoadCompleteListener. Here is a small example for this: Android sounds tutorial.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文