Android Media Player Seek bar在停止后启动时不会更新

时间:2012-01-21 11:36:56

标签: java android multithreading seekbar android-mediaplayer

我正在努力解决这个问题。

我有一个媒体播放器,我可以暂停,暂停,停止,再次播放,停止......无论如何。 现在我希望有一个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 :(得分:0)

我在这里看到三个问题:

首先,这部分:

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

第一次运行在线程代码中将threadStarted设置为true的线程,但是当线程完成时,您永远不会将其设置回false。所以在第一次运行之后它将永远是true,因此上面的else将始终执行,顺序运行播放器代码,从而阻止您的用户界面。

第二次,您正在从与UI线程不同的线程更新用户界面(SeekBar)。有关如何在这种情况下正确更新用户界面,请参阅此相关问题:Update UI from Thread

第三,这可能只是一个建议,但由于您的threadStarted变量在线程之间进行了修改,因此最好将其声明为volatile以防止某些优化破坏您的代码:

private volatile boolean threadStarted = false;

答案 1 :(得分:-1)

根据我的经验以及docs中的内容,Android中的线程仅在编程的纯粹algorythmic部分工作。任何尝试在活动中使用它们或任何连接到UI的东西都会出错。这样它就不会起作用。 从不可以修复它!

使用AsyncTask(或更多内容的子Activity / Fragment)。