Я решил эту проблему в своем приложении следующим образом:
Создание объектов для AsyncTasks (чтобы вы могли проверить, выполняются ли они):
private AsyncTask<String, Void, String> releaseMP;
private AsyncTask<String, Void, String> setSource;
Создайте AsyncTask для подготовительного вызова:
private class setSource extends AsyncTask<String, Void, String> {
@Override
protected synchronized String doInBackground(final String... urls) {
try {
mMediaPlayer.prepare();
} catch (final IllegalStateException e) {
e.printStackTrace();
return e.getMessage();
} catch (final IOException e) {
e.printStackTrace();
return e.getMessage();
} catch (final Exception e) {
e.printStackTrace();
return e.getMessage();
}
return null;
}
@Override
protected void onCancelled() {
if (setSource != null)
setSource = null;
// Send error to listener
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
releaseMP = new releaseMP().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
@Override
protected void onPostExecute(final String result) {
if (setSource != null)
setSource = null;
// Check for error result
if (result != null) {
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
@Override
protected void onPreExecute() {
}
}
Теперь ваш код подготовки:
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mDuration = -1;
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(getContext(), mUri, mHeaders);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
// mMediaPlayer.prepareAsync();
// we don't set the target state here either, but preserve the
// target state that was there before.
mCurrentState = STATE_PREPARING;
} catch (final IOException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
} catch (final IllegalArgumentException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
} catch (final Exception ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
}
setSource = new setSource().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
И, наконец, когда вам нужно убить mediaPlayer, вы проверите объект setSource, чтобы убедиться, что он готовится, прежде чем его отпустить. Если он готовится, вы отмените AsyncTask и в AsyncTask onCancelled сбросите и отпустите объект:
public void release(final boolean cleartargetstate) {
if (mMediaPlayer != null) {
if (setSource != null) {
setSource.cancel(true);
} else {
releaseMP = new releaseMP().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
}
}
А это мой releaseMP AsyncTask (который просто сбрасывает и освобождает объект):
private class releaseMP extends AsyncTask<String, Void, String> {
@Override
protected synchronized String doInBackground(final String... urls) {
Log.i(MethodNameTest.className() + "." + MethodNameTest.methodName(), "called");
if (mMediaPlayer != null) {
// Release listeners to avoid leaked window crash
mMediaPlayer.setOnPreparedListener(null);
mMediaPlayer.setOnVideoSizeChangedListener(null);
mMediaPlayer.setOnCompletionListener(null);
mMediaPlayer.setOnErrorListener(null);
mMediaPlayer.setOnBufferingUpdateListener(null);
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
return null;
}
@Override
protected void onPostExecute(final String result) {
Log.i(MethodNameTest.className() + "." + MethodNameTest.methodName(), "called");
if (releaseMP != null)
releaseMP = null;
}
}