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

Posted

技术标签:

【中文标题】了解在 Android 1.6/2.0/2.1 上使用 SoundPool 加载声音是不是成功【英文标题】:Knowing if the loading of a sound with SoundPool has been successful on Android 1.6/2.0/2.1了解在 Android 1.6/2.0/2.1 上使用 SoundPool 加载声音是否成功 【发布时间】:2011-01-14 15:19:31 【问题描述】:

android 2.2+ 上,有一个名为 SoundPool.OnLoadCompleteListener 的东西可以知道声音是否已成功加载。

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

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

【问题讨论】:

好问题,我也遇到了同样的问题 (***.com/questions/3253108/…),但并没有真正找到解决方案。 【参考方案1】:

我实现了一种兼容的 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();
        
    

【讨论】:

【参考方案2】:

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

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

【讨论】:

以上是关于了解在 Android 1.6/2.0/2.1 上使用 SoundPool 加载声音是不是成功的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何在 Android 地址上了解一个国家是不是有州?

Android:了解APK安装过程

Android内存优化1 了解Android是如何管理App内存

带您了解PAX:Android网络交叉许可协议

Android 设计模式 笔记 - 深入了解WindowManager

Android 弹性布局 FlexboxLayout了解一下