首页 文章

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

提问于
浏览
1

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

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

    我在这里看到三个问题:

    First ,这部分:

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

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

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

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

    private volatile boolean threadStarted = false;
    
  • -1

    根据我的经验以及docs中的内容,Android中的线程仅在prog的纯粹algorythmic部分工作 . 任何尝试在活动中使用它们或任何连接到UI的东西都会出错 . 这种方式根本不起作用 . Never 你能修复它吗!

    而是使用AsyncTask(或者用于更多事情的子Activity / Fragment) .

相关问题