Слишком скоро отключится звук медиапланера

У меня есть два устройства, на которых я могу протестировать свою игру: телефон США Celluar (SCH-R880) и Kindle Fire, Kindle Fire намного мощнее, чем телефон.

У меня есть несколько коротких (менее или около 1 секунды) звуковых эффектов. Для сохранения в памяти я загружаю, воспроизвожу и отпускаю некоторые из этих звуковых эффектов. По телефону они играют (в основном), как и ожидалось. Однако на Kindle Fire они прерваны. Очень короткие звуки отрезаны так быстро, что я ничего не слышу. Тем не менее, те, которые загружены при настройке и остаются, отлично выглядят.

Кто-нибудь знает, что здесь происходит? Я как-то рано высвобождаю свои СМИ? Ниже приведен один пример этого. По телефону слышу "Второй уровень!" но на Kindle я слышу что-то вроде "Lev tw."

mpNum = null;

try
{
    switch (level)
    {
        case 2:
            mpNum = MediaPlayer.create(contxt, R.raw.l2); break;
        case 3:
            mpNum = MediaPlayer.create(contxt, R.raw.l3); break;
        case 4:
            mpNum = MediaPlayer.create(contxt, R.raw.l4); break;
        case 5:
            mpNum = MediaPlayer.create(contxt, R.raw.l5); break;
        case 6:
            mpNum = MediaPlayer.create(contxt, R.raw.l6); break;
        case 7:
            mpNum = MediaPlayer.create(contxt, R.raw.l7); break;
        case 8:
            mpNum = MediaPlayer.create(contxt, R.raw.l8); break;
        default:
            return;
    }

    MediaPlayer vLevel = MediaPlayer.create(contxt, R.raw.level);

    vLevel.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
    {
        public void onPrepared(MediaPlayer mp)
        {
            mp.start();
        }
    });

    vLevel.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
    {
           public void onCompletion(MediaPlayer mpl)
           {
            mpNum.start();
            mpl.release();
           }
       });

        mpNum.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
        {
            public void onCompletion(MediaPlayer mp)
            {
                mp.release();
            }
        });
    }
    catch (Exception e) {}

В попытке исправить это, я попробовал SoundPool, но он не работает; Я ничего не слышу. Ниже я попытался воспроизвести музыку с помощью SoundPool:

SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100);
    soundPool.load(contxt, R.raw.song2, 1);
    AudioManager mgr = (AudioManager)contxt.getSystemService(Context.AUDIO_SERVICE);
    float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
    float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
    float volume =  streamVolumeMax;  

    soundPool.play(1, volume, volume, 1, 5, 2);

UPDATE

Я заметил, когда звук, который должен воспроизводиться (но не имеет), имеет эту ошибку:

AudioPolicyManager: stopOutput() oldDevice 2
AudioPolicyManager: [getDeviceForStrategy] strategy : 0,forceUse(0)

Ответ 1

Это странно, и не очень хорошее исправление, но единственное исправление, которое я нашел до сих пор. Если я удалю mp.setOnPreparedListener и mp.setOnCompletionListener и просто mp.start(), он будет работать.

Ответ 2

У меня была такая же проблема, и это действительно была проблема сборщика мусора! Если вы назначаете экземпляр медиаплеера какой-либо локальной переменной внутри метода, экземпляр больше не существует после выхода из этого метода, поэтому GC может случайно удалять его в любое время.

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

private static Set<MediaPlayer> activePlayers = new HashSet<MediaPlayer>();

Затем создается медиаплеер:

MediaPlayer player = MediaPlayer.create(context, context.getResources().getIdentifier(id, "raw", pkg));
activePlayers.add(player);
player.setOnCompletionListener(releaseOnFinishListener);
player.start();

Где releaseOnFinishListener - это слушатель, который выпускает медиаплеер на финише точно так же, как ваш, но также удаляет указатель из набора activePlayers:

MediaPlayer.OnCompletionListener releaseOnFinishListener = new MediaPlayer.OnCompletionListener() {
    public void onCompletion(MediaPlayer mp) {
        mp.release();
        activePlayers.remove(mp);
    }
};

Надеюсь, это поможет вам.

Ответ 3

Я читал, что класс SoundPool больше подходит для таких коротких звуков, как MediaPlayer, но это, вероятно, не проблема. (здесь ссылка на пример SoundPool).

Можете ли вы также опубликовать код для вашего обработчика кликов?

Кроме того, я бы рекомендовал, а не выпускать и восстанавливать экземпляры MediaPlayer, использовать один экземпляр MediaPlayer и просто следовать типичной последовательности reset(), setDataSource(), prepare(), start() всякий раз, когда вам нужно повторно использовать Это. Это будет более эффективно, чем создание нового экземпляра каждый раз. то есть:

MediaPlayer mp = new MediaPlayer();
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.sound1);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength();
mp.prepare();
mp.start();

//to reuse
mp.reset();
afd = getResources().openRawResourceFd(R.raw.sound2);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength();
mp.prepare();
mp.start();

Ответ 4

Ну, у меня были одни и те же проблемы в одном проекте, и потому, что в KindleFire звуки вырезаны перед финишем, поэтому, чтобы исправить это (с выпуском), я добавил задержку в релизе:

    mpNum.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
    {
        public void onCompletion(MediaPlayer mp)
        {
            // Add a handler delay
            new Timer().schedule(new TimerTask() {

                @Override
                public void run() {
                   mp.release();
               }
            }, DELAY_TIME);
        }
    });

Это не лучшее решение, но я думаю, что, возможно, это поможет вам.

Ответ 5

У меня была эта проблема, и я решил, что мой объект MediaPlayer является приватным, поэтому сборщик мусора не очищает экземпляр. Надеюсь, это поможет кому-то!