Android Media Player 搜索栏在停止后启动时不更新
我很难处理这个问题。
我有一个媒体播放器,我可以播放、暂停、停止、暂停后再次播放、停止......等等。 现在我想要一个 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();
}
}
}
}
I'm having a hard time working with this.
I have a Media player, and I can play, pause, stop, play again after pause, stop... whatever.
Now I wanted to have a SeekBar to give a visual component. My problem is:
When I start the player for the first time everything works well. Music plays, and seek bar updates. also works when I pause.
Now, if I stop the player and start it again, the player starts, the run() method executes, but the seekbar doesn't update, and soon the app gives a not responging error.
What am I missing here?
The run method is an implementation from the Runnable interface, and with a simple log, I can see it's being executed, even after the stop/play case. The only thing that seems not to be working is the seek.setProgress(...).
some help, please? :)
Here's my code:
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();
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我在这里看到三个问题:
首先,这部分:
第一次运行线程时,您在线程代码中将
threadStarted
设置为true
,但是当线程结束时,你永远不会将其设置回false
。因此,在第一次运行后,它将永远为true
,因此上面的else
将始终执行,按顺序运行播放器代码,从而阻塞您的用户界面。第二,您正在从与 UI 线程不同的线程更新用户界面(
SeekBar
)。请参阅此相关问题,了解在这种情况下如何正确更新 UI:从线程更新 UI<第三,这可能只是一个建议,但由于您的
threadStarted
变量在线程之间修改,因此最好将其声明为易失性
以防止某些优化破坏你的代码:I see three issues here:
First, this part:
The first time your run the thread you set
threadStarted
totrue
in the thread code, but you never set it back tofalse
when the thread finishes. So after the first run it will betrue
forever and thus theelse
above will always execute, running the player code sequentially and thus blocking your user interface.Second, you are updating the user interface (the
SeekBar
) from a different thread than the UI thread. See this related question for how to correctly update the UI in this case: Update UI from ThreadThird, this may be just a recommendation, but since your
threadStarted
variable is modified between threads, it's better to declare itvolatile
to prevent some optimizations from breaking your code:根据我的经验以及 docs,Android 中的线程仅在程序的纯算法部分工作。任何在活动中使用它们的尝试,或者任何与 UI 连接的东西,都会出错。这样根本行不通。 永远你无法修复它!
请使用 AsyncTask(或子 Activity/Fragment 来实现更大的事情)。
According to my experience and what is written in docs, threads in Android work only in purely algorythmic parts of a prog. Any try to use them in activities, or anything connected to UI, goes to error. This way it simply won't work. Never can you repair it!
Use AsyncTask (or child Activity/Fragment for greater things) instead.