Android Media Player Панель поиска не обновляется при запуске после остановки - PullRequest
1 голос
/ 21 января 2012

Мне трудно с этим работать.

У меня есть медиаплеер, и я могу воспроизводить, ставить на паузу, останавливать, воспроизводить снова после паузы, останавливать ... что угодно.Теперь я хотел иметь SeekBar для создания визуального компонента.Моя проблема: при первом запуске плеера все работает хорошо.Музыка играет, и искать обновления бара.также работает, когда я пауза.

Теперь, если я остановил проигрыватель и запустил его снова, проигрыватель запускается, метод run () запускается, но панель поиска не обновляется, и вскоре приложение выдает ошибку, которая не возникает.Что мне здесь не хватает?

Метод run является реализацией из интерфейса Runnable, и с помощью простого журнала я вижу, что он выполняется даже после случая остановки / воспроизведения.Единственное, что, похоже, не работает - это seek.setProgress (...).помогите, пожалуйста?:)

Вот мой код:

public class MediaPlayerTestingActivity extends Activity 
               implements OnClickListener, OnPreparedListener, Runnable {

private MediaPlayer mp;
private boolean paused = false;
private SeekBar seek;
private boolean threadStarted = false;;
private Thread thread = new Thread(this);


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    seek = (SeekBar)findViewById(R.id.seek);
    mp = new MediaPlayer();

    Button start = (Button)findViewById(R.id.start);
    start.setOnClickListener(this);
    Button pause = (Button)findViewById(R.id.pause);
    pause.setOnClickListener(this);
    Button stop = (Button)findViewById(R.id.stop);
    stop.setOnClickListener(this);

}

//click handlers
public void onClick(View v) 
{
    int buttonId = v.getId();

    switch (buttonId)
    {
        case R.id.start:
            if(mp != null)
            {
                if(!mp.isPlaying() && !paused)
                    prepareTostartPlayer();
                else
                    mp.start(); //if it was just paused
            }
            else
            {
                mp = new MediaPlayer();
                prepareTostartPlayer();
            }
            break;
        case R.id.pause:
            if(mp.!= null && mp.isPlaying())
            {   
                mp.pause();
                paused = true;
            }
            break;

        case R.id.stop:
            if(mp != null && mp.isPlaying())
            {
                mp.stop();
                mp.release();
                mp = null;
            }
            break;

        default:
            break;
    }
}

//When the player is ready to play
public void onPrepared(MediaPlayer arg0) 
{
    seek.setMax(mp.getDuration());
    mp.start(); 
    if(!threadStarted)
        thread.start();
    else
        thread.run();
}

//Method to prepare to start the player
private void prepareTostartPlayer()
{
    mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
    try {
        mp.setDataSource("http://feedproxy.google.com/~r/rc-cadernetadecromos/~3/JH1kfZCmP3M/cdc_190112_2.mp3");
        mp.prepareAsync();
        mp.setOnPreparedListener(this);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void run() 
{
    threadStarted   = true;
    int current = 0;
    while(mp != null && current < mp.getDuration())
    {
        try {
            current = mp.getCurrentPosition();
            seek.setProgress(current);
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }       
}

}

Ответы [ 2 ]

0 голосов
/ 21 января 2012

Согласно моему опыту и тому, что написано в документах , потоки в Android работают только в чисто алгоритмических частях прог. Любая попытка использовать их в действиях или что-либо, связанное с пользовательским интерфейсом, приводит к ошибке. Таким образом, это просто не будет работать. Никогда Вы можете починить его!

Вместо этого используйте AsyncTask (или дочернюю активность / фрагмент для более важных вещей).

0 голосов
/ 21 января 2012

Здесь я вижу три вопроса:

Первый , эта часть:

public void onPrepared(MediaPlayer arg0) 
{
    seek.setMax(mp.getDuration());
    mp.start(); 
    if(!threadStarted)
        thread.start();
    else
        thread.run();
}

При первом запуске потока вы устанавливаете threadStarted на true в коде потока, но никогда не устанавливаете его обратно на false после завершения потока. Таким образом, после первого запуска это будет true навсегда, и, следовательно, else выше всегда будет выполняться, последовательно выполняя код проигрывателя и, таким образом, блокируя ваш пользовательский интерфейс.

Второй , вы обновляете пользовательский интерфейс (SeekBar) из потока, отличного от потока пользовательского интерфейса. См. Этот связанный вопрос о том, как правильно обновить пользовательский интерфейс в этом случае: Обновить пользовательский интерфейс из потока

Третий , это может быть просто рекомендация, но, поскольку ваша переменная threadStarted изменяется между потоками, лучше объявить ее volatile, чтобы предотвратить некоторые оптимизации вашего кода:

private volatile boolean threadStarted = false;
...