SoundPool 仅在第一次播放声音

Posted

技术标签:

【中文标题】SoundPool 仅在第一次播放声音【英文标题】:SoundPool plays sound only the first time 【发布时间】:2017-06-12 15:49:58 【问题描述】:

我想在每次点击视图时播放声音:

我创建了一个简单的效果播放器:

public class EffectManager 

private static SoundPool soundPool;
private static int puzzlePieceOK;
private static int puzzleOK;


public static void init(Context context) 
    if (soundPool == null) 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
            soundPool = new SoundPool.Builder()
                    .setAudioAttributes(new AudioAttributes.Builder()
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .setUsage(AudioAttributes.USAGE_GAME)
                            .build()
                    )
                    .setMaxStreams(10)
                    .build();
        
        else 
            soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 1);
        
        puzzlePieceOK = soundPool.load(context,R.raw.puzzle_piece_ok,1);
        puzzleOK = soundPool.load(context,R.raw.puzzle_ok,1);
    


public static void playPuzzlePieceOK() 
    soundPool.play(puzzlePieceOK,10,10, 1,0,1);


public static void playPuzzleOK() 
    soundPool.play(puzzleOK,10,10, 1,1,1);



我在我的活动的onCreate 事件上致电EffectManager.init。然后我将此侦听器添加到我的视图中:

setOnClickListener(new OnClickListener() 
        @Override
        public void onClick(View v) 
            EffectManager.playPuzzlePieceOK();
        
    );   

当我只点击第一个视图时,我可以听到声音。我尝试了不同的单击视图顺序,声音仅在第一次单击时播放。除了这个警告,我在控制台上没有任何消息错误。 :

W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by server

此警告仅在第一次点击时出现。

【问题讨论】:

【参考方案1】:

我也有同样的问题,我认为使用 SDK >= LOLLIPOP 的 SoundPool 中存在问题。 我找不到一个完美的解决方案,但一个很好的解决方法。 我解决了,重新加载原始内容再播放。

我正在使用我的类 SoundManager,它很有用。

import java.util.HashMap;
import java.util.Iterator;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;

import it.aldea.android.Log;
import it.aldea.util.Utils;

public class SoundManager 

    private SoundPool mSoundPool;
    private HashMap<Integer, Integer> mSoundPoolMap;
    private AudioManager mAudioManager;
    private Context mContext;
    private int streamId;
    private boolean initialized = false;
    protected Log log;

    public SoundManager() 
        mSoundPoolMap = new HashMap<Integer, Integer>();
    

    public SoundManager(Log log) 
        this();
        this.log = log;
    

    public void initSounds(Context theContext) 
        mContext = theContext;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
            mSoundPool = new SoundPool.Builder()
                    .setAudioAttributes(new AudioAttributes.Builder()
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .setUsage(AudioAttributes.USAGE_GAME)
                            .build()
                    )
                    .setMaxStreams(10)
                    .build();
         else 
            mSoundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
        
        mSoundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() 

            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) 
                initialized = true;
            
        );
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
    

    public void reset() 
        //initSounds(mContext);
        reloadSound();
    

    public void reloadSound() 
        Iterator iterator = mSoundPoolMap.keySet().iterator();
        while (iterator.hasNext()) 
            int soundID = (Integer) iterator.next();
            mSoundPoolMap.put(soundID, mSoundPool.load(mContext, soundID, 1));
        
    

    public void addSound(int soundID) 
        mSoundPoolMap.put(soundID, mSoundPool.load(mContext, soundID, 1));
    

    public void clearSounds() 
        mSoundPoolMap.clear();
    


    private void waitInit() 

        for (int i = 0; !isInitialized() && i < 10; i++) 
                if (log != null && log.isDebugEnabled()) log.d("Wait SoundPool initialized n." + i);
                Utils.sleep(100);
        
        if (!isInitialized()) 
            if (log != null) 
                log.e("SoundPool NOT initialized");
             else 
                System.err.println("SoundPool NOT initialized");
            
        
    

    public void playSingleSound(int resourceId, boolean forever) 
        int repeat = forever ? -1 : 0;
        int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        waitInit();
        for (int i = 0; i < 3; i++) 
            int poolId = mSoundPoolMap.get(resourceId);
            streamId = mSoundPool.play(poolId, streamVolume, streamVolume, 1, repeat, 1f);
            if (streamId > 0) 
                break;
             else 
                Utils.sleep(300);
            
        
        if (streamId == 0) 
            if (log != null) 
                log.e("playSound without streamId for index :" + resourceId);
            
        
    

    public void playSound(int index) 
        playSingleSound(index, false);
    

    public void playLoopedSound(int index) 
        if (log != null && log.isDebugEnabled()) 
            log.d("playLoopedSound soundId:" + index);
        
        playSingleSound(index, true);
    

    public void stopLastSound() 
        if (log != null && log.isDebugEnabled()) 
            log.d("stopLastSound");
        
        if (streamId > 0) 
            mSoundPool.stop(streamId);
        
        streamId = 0;
    

    public boolean isInitialized() 
        return initialized;
    

    public void setInitialized(boolean initialized) 
        this.initialized = initialized;
    

    public void close() 
        mSoundPool.release();
    

供使用:

// Init
mSoundManager = new SoundManager();
mSoundManager.initSounds(getBaseContext());
mSoundManager.addSound(R.raw.SOUND_BEEP2); 
mSoundManager.addSound(R.raw.SOUND_BEEP);
mSoundManager.addSound(R.raw.SOUND_ANNOYING_ALARM);


// Use
mSoundManager.reset();
mSoundManager.playSound(R.raw.SOUND_BEEP2);

希望对您有所帮助。

【讨论】:

以上是关于SoundPool 仅在第一次播放声音的主要内容,如果未能解决你的问题,请参考以下文章

在android soundpool中播放新声音时如何停止所有其他以前的声音?

SoundPool 不播放声音

Sound Pool 只播放一次声音

使用 SoundPool 播放声音

使用 SoundPool 播放声音

如何使用 SoundPool 播放随机声音?