В моем случае я хочу транслировать аудио и показывать его прогресс на простом ProgressBar, я не мог найти обработчик событий для воспроизведения прогресса, все, что я нашел в Интернете, это то, что я могу сделать Runnable и запустить его в play () как следует

public void fireRunnable()
{
    Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {
            int duration = mediaPlayer.getDuration();
            while( mediaPlayer.isPlaying() )
            {
                Log.v("", mediaPlayer.getCurrentPosition()+"");
            }
        }
    };
    runnable.run();
}

И вызывайте его сразу после игры в onPrepared ()

@Override
public void onPrepared(MediaPlayer arg0)
{
    arg0.start();
    fireRunnable();
}

Теперь песня начинается без звука, и приложение вылетает примерно через 5 секунд после этого, это хороший подход, если да, как я могу заставить его работать? или нет какие еще варианты у меня есть?
Помощь будет признательна.

2
Ahmad Dwaik 'Warlock' 1 Окт 2013 в 17:40

1 ответ

Лучший ответ

Если вы решите использовать Runnable, как вы показали, вы захотите запустить его в другом Thread и использовать post(Runnable) для внесения изменений в поток пользовательского интерфейса. Упомянутый вами сбой, вероятно, происходит из-за очень активного цикла while в вашем потоке пользовательского интерфейса. Даже при запуске отдельного потока вы захотите вызвать Thread.sleep(long) в своем цикле, чтобы получить некоторое время процессора, поскольку индикатор выполнения не должен быть настолько невероятно точным.

Другой метод - использовать postDelayed(Runnable, long) с Runnable, который многократно повторно публикует себя после небольшой задержки (например, 500 миллисекунд). В зависимости от обстоятельств этот метод, вероятно, предпочтительнее, поскольку он позволяет избежать лишнего потока.

Также обратите внимание, что isPlaying() будет ложным, если MediaPlayer приостановлено. Было бы лучше использовать логический член в качестве условия прекращения обновления индикатора выполнения. Установите для него значение true, прежде чем начинать обновление индикатора выполнения, и установите для него значение false в обратном вызове OnCompletionListener.onCompletion() для MediaPlayer.

Редактировать:

Когда я упомянул post(Runnable) для потока пользовательского интерфейса, я имел в виду тот факт, что внесение изменений в элементы пользовательского интерфейса из других потоков является незаконным. В этом случае вы, вероятно, не изменяете элементы пользовательского интерфейса явно, а только состояние индикатора выполнения, что должно быть в порядке.

Изменить: (версия postDelayed)

В вашем Activity:

private boolean mUpdateProgress = false;
private Runnable mUpdateRunnable = new Runnable() {
    @Override
    public void run() {
        // update progress bar using getCurrentPosition()
        if (mUpdateProgress)
            postDelayed(mUpdateRunnable, 500);
    }
}
private MediaPlayer.OnCompletionListener mComplete =
    new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion() {
            mUpdateProgress = false;
        }
    }

Где бы вы ни создавали свой MediaPlayer, звоните:

mediaPlayer.setOnCompletionListener(mComplete);

Где бы вы ни запустили MediaPlayer, сделайте следующее:

// update the duration of the progress bar
mUpdateProgress = true;
post(mUpdateRunnable); // or simply mRunnable.run() if you are on the main thread
mediaPlayer.start();
5
Dave 2 Окт 2013 в 11:40
Да, это отлично работает, спасибо, но у меня есть еще два вопроса, как вы можете видеть в моем runnable, я вызываю isPlaying (), чтобы проверить, обновлять или нет, если я приостановлю воспроизведение, он больше не будет обновляться, что правильно, тогда я позвоню прервать или убить поток или просто оставить его в покое? Второй вопрос: где мне вызвать сообщение (Runnable), которое вы упомянули для обновления пользовательского интерфейса, можете ли вы опубликовать код?
 – 
Ahmad Dwaik 'Warlock'
2 Окт 2013 в 10:43
Используя isPlaying() в условии while, ваш поток завершится, когда MediaPlayer будет приостановлено. Он больше не будет обновлять индикатор выполнения даже после возобновления воспроизведения. Я отредактирую свой ответ, чтобы продемонстрировать метод postDelayed.
 – 
Dave
2 Окт 2013 в 11:20