我是Android开发新手,我需要一些帮助来解决一个小问题。我有一个后台服务,运行我的媒体播放器,并与我的PlayerActivity通信。到目前为止一切顺利。
我需要安排不同时期的曲目执行。例如,播放音轨x一分钟,播放音轨y 30秒,等等。
所以我从PlayerActivity调用MyTimer线程,这个线程在特定的时间抛出事件,PlayerActivity捕获事件并调用MediaplayerService next()方法。我的问题是,如果我调用next()没有线程它工作得很好,如果我调用它与线程,我得到
mContext is null, can't getMirrorDisplayStatus!!!
with mediaplayer warning (1,2002)我试图通过Handler.post()和runOnUiThread()从PlayerActivity运行这个线程我得到同样的错误
下面是MyTimer线程的代码。public class MyTimer implements Runnable {
private Object mPauseLock;
private boolean mPaused;
private boolean mFinished;
private TimeSection section;
public Trainer()
{
mPauseLock = new Object();
mPaused = false;
mFinished = false;
BusProvider.getInstance().register(this);
}
@Override
public void run()
{
while (!mFinished)
{
TimerManager tm = TimerManager.getInstace();
this.section = tm.getCurrentTimeSection();
if(this.section == null)
mFinished = true;
else
{
tm.inc();
// produce sectionChangeEvent event
BusProvider.getInstance().post(produceSectionEvent());
try
{
Thread.sleep((this.section.getTypeDuration() * 1000));
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized (mPauseLock)
{
while (mPaused)
{
try
{
mPauseLock.wait();
} catch (InterruptedException e)
{
}
}
}
}
}
/**
* Call this on pause.
*/
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}
/**
* Call this on resume.
*/
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();
}
}
@Produce public TimeSectionEvent produceSectionEvent(){
return new TimeSectionEvent(this.section);
}
}
一些玩家活动的代码:
public class PlayerActivity implements
IMediaPlayerServiceClient{
private MediaPlayerService mService;
....
/**
* Binds to the instance of MediaPlayerService. If no instance of
* MediaPlayerService exists, it first starts a new instance of the service.
*/
public void bindToService()
{
Intent intent = new Intent(this, MediaPlayerService.class);
if (MediaPlayerServiceRunning())
{
// Bind to LocalService
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
} else
{
startService(intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
}
.....
/*
* This is how I start the timing thread
*/
private void startTiming()
{
mTimer = new MyTimer();
runOnUiThread(mTimer);
// trainingHandler.post(mTrainer);
}
public void next(TimeSection section)
{
mService.next(section);
}
/*
* Here I catch the TimeSectionEvent from MyTimer thread
*/
@Subscribe public void onSectionChanged(TimeSectionEvent e)
{
TimeSection section = e.getSection();
if(section != null)
next(section);
}
每个活动都有上下文,所以从异常,你得到我猜这是一个问题与MediaPlayerService的上下文。
你正在使用bindService(…)将意图绑定到应该绑定上下文的MediaPlayerService。
尝试检查绑定是否仍然存在,当你试图执行"mService.next(section);"
问题解决!
问题是,我是计时线程运行在UI线程->调用Thread.sleep
使UI线程睡眠以及。所以我最终使用IntentService
在后台做定时器线程工作。
public class TimingService extends IntentService{
private Object mPauseLock;
private boolean mPaused;
private boolean mFinished;
private TimeSection section;
public TimingService()
{
super("TimingService");
mPauseLock = new Object();
mPaused = false;
mFinished = false;
BusProvider.getInstance().register(this);
}
@Override
protected void onHandleIntent(Intent intent)
{
while (!mFinished)
{
TimerManager tm = TimerManager.getInstace();
this.section = tm.getCurrentTimeSection();
if(this.section == null)
mFinished = true;
else
{
tm.inc();
// produce sectionChangeEvent event
BusProvider.getInstance().post(produceSectionEvent());
try
{
Thread.sleep((this.section.getTypeDuration() * 1000));
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized (mPauseLock)
{
while (mPaused)
{
try
{
mPauseLock.wait();
} catch (InterruptedException e)
{
}
}
}
}
}
/**
* Call this on pause.
*/
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}
/**
* Call this on resume.
*/
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();
}
}
@Produce public TimeSectionEvent produceSectionEvent(){
return new TimeSectionEvent(this.section);
}
@Subscribe
public void onPauseEvent(PauseEvent e)
{
this.onPause();
}
@Subscribe
public void onResumeEvent(ResumeEvent e)
{
this.onResume();
}
}