我正在努力解决这个问题。
我有一个媒体播放器,我可以暂停,暂停,停止,再次播放,停止......无论如何。 现在我希望有一个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();
}
}
}
}
答案 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)。