#java #android #multithreading #service #android-mediaplayer
#java #Android #многопоточность #Обслуживание #android-mediaplayer
Вопрос:
Я новичок в разработке Android, и мне нужна помощь в решении небольшой проблемы. У меня есть фоновая служба, которая запускает мой медиаплеер и взаимодействует с моим PlayerActivity. Пока все хорошо.
Мне нужно запланировать выполнение дорожек в разные периоды. т.е. Воспроизвести дорожку x в течение одной минуты, чем воспроизвести дорожку y в течение 30 секунд и т.д.
Итак, я вызываю поток MyTimer из PlayerActivity, этот поток генерирует событие в определенное время,
PlayerActivity улавливает событие и вызывает метод MediaPlayerService next(). Моя проблема в том, что если я вызываю next() без потока, он работает нормально, если я вызываю его с потоком, который я получаю
mContext is null, can't getMirrorDisplayStatus!!!
с предупреждением mediaplayer (1, 902)
Я попытался запустить этот поток из PlayerActivity через Handler.post() и runOnUiThread()
, и я получаю ту же ошибку.
ниже приведен код для потока 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);
}
Ответ №1:
каждое действие имеет контекст, поэтому из исключения, которое вы получили, я предполагаю, что это проблема с контекстом MediaPlayerService.
вы используете bindService(…) для привязки намерения к MediaPlayerService, который должен привязывать контекст.
попробуйте проверить, сохраняется ли эта привязка, когда вы пытаетесь выполнить «mService.next (раздел);»
Комментарии:
1. Я проверил это, и он все еще связан … 🙁
Ответ №2:
Проблема РЕШЕНА!
Проблема заключалась в том, что я заключался в том, что поток синхронизации выполнялся в потоке пользовательского интерфейса -> вызов Thread.sleep
также привел к отключению потока пользовательского интерфейса. Итак, я в конечном итоге использую 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();
}
}