SoundPool воспроизводит звук только в первый раз

Я хочу воспроизводить звук каждый раз при нажатии на представление:

Я создал простой проигрыватель эффектов:

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);
}

}

Я вызываю EffectManager.init по событию onCreate моей активности. Затем я добавляю этот слушатель в свои представления:

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

Я мог слышать звук, когда я нажимаю только на первый вид. Пробовал другой порядок нажатия просмотров, звук играет только при первом нажатии. У меня нет никаких сообщений об ошибках на консоли, кроме этого предупреждения. :

W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by server

Это предупреждение появляется только при первом нажатии.


person ALAA    schedule 12.06.2017    source источник


Ответы (1)


У меня та же проблема, и я думаю, что проблема в SoundPool с SDK >= LOLLIPOP. Я не могу найти идеальное решение, но хороший обходной путь. Я решил это, перезагрузите необработанный контент, прежде чем снова играть.

Я использую свой класс 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);

Я надеюсь, что это поможет вам.

person iLoveCode    schedule 14.10.2017