Запланировать выполнение mediaplayer в Android

#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();
}
}