Мое приложение работает нормально, но я получаю предупреждения MediaPlayer finalized without being released
, и я не уверен, почему я их получаю. Странно то, что они появляются только тогда, когда я использую MediaPlayer.create(ctxt, resid)
для воспроизведения файлов ресурсов (.ogg), а не когда я использую setDataSource(path)
для воспроизведения файлов с SD-карты.MediaPlayer завершен без выпуска
Я просмотрел много других сообщений о переполнении стека, просмотрел документы разработчиков и пробовал разные комбинации вещей (слишком много, чтобы их перечислить), но ничто не избавляет от этой ошибки. Не уверен, что это ошибка или что-то, что я делаю.
Я использую ViewPager с FragmentStatePagerAdapter и в основном, когда вы нажимаете на страницу, он воспроизводит звук. Когда вы переходите на следующую страницу, он останавливает воспроизведение звука (если он все еще воспроизводится). Вот код для этой части, но я удалил его во время испытаний, и это, кажется, не делают разницы, но я решил включить его только в случае, если:
public void stopAudioInFragment() {
ViewPageFragment page = (ViewPageFragment)
getSupportFragmentManager().findFragmentById(R.id.pager);
if (page != null) {
page.stopAudio();
}
}
Вот соответствующий код фрагмент:
public static MediaPlayer mPlayer;
private int mAudioId;
private boolean mIsAudioFile = false;
public void playAudio() {
// Setup media player to play audio
mIsAudioFile = false;
stopAudio();
mPlayer = new MediaPlayer();
if (!mIsAudioFile && mAudioId != -1 && mPlayer != null) {
// Play local resource audio
mPlayer = MediaPlayer.create(mContext, mAudioId);
mPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stopAudio();
}
});
} else if (mAudioId != -1 && mPlayer != null) {
// Play audio file on SD card
try {
mPlayer.setDataSource(audio_file_path);
mPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stopAudio();
}
});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mPlayer.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mPlayer.start();
}
public void stopAudio() {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
mPlayer.stop();
}
mPlayer.reset(); // Might not be necessary, since release() is called right after, but it doesn't seem to hurt/cause issues
mPlayer.release();
mPlayer = null;
}
}
@Override
public void onDestroy() {
stopAudio();
super.onDestroy();
}
Опять же, вышеизложенное прекрасно работает и, похоже, не вызывает никаких проблем. Если я нахожусь на странице и нажимаю ее несколько раз, она начинает воспроизводить звук, а затем останавливается/играет с каждым новым нажатием. Похоже, что предупреждения появляются, когда он разрушает страницу, а затем работает GC. При каждом воспроизведении аудиофайла есть одно предупреждение.
Я хотел бы знать, почему я получаю предупреждения MediaPlayer finalized without being released
только тогда, когда он воспроизводит файлы ресурсов, а не когда он воспроизводит файлы с SD-карты. Насколько я могу судить, он всегда должен быть доработан до того, как он будет GC'd. Есть идеи?
Обновление: Я сделал еще несколько тестов, чтобы попытаться выяснить, могу ли я что-то сказать «странно», но единственное, что я действительно вижу, это то, что оно влияет только на файлы в папке res/raw. Вот что я могу добавить:
- Файлы, генерирующие предупреждения, находятся в папке res/raw.
- Если я перемещаю файлы (.ogg, а также проверенные с помощью .wav) в папку с ресурсами и воспроизвожу их там, , MediaPlayer НЕ генерирует никаких предупреждений.
- Я заменил некоторые файлы в res/raw с .mp3, .wav и .mp4 аудиофайлами, и они ВСЕ ПОКАЗЫВАЕМЫЕ ПРЕДУПРЕЖДЕНИЯ, как и оригинальные файлы .ogg.
- Я успешно воспроизводил файлы .mp3, .wav и .mp4 с SD-карты, а DID NOT генерирует предупреждения MediaPlayer.
- Чтобы уточнить: все файлы воспроизводятся без проблем с точки зрения пользователей . То, что я пытаюсь понять, - это то, почему MediaPlayer генерирует предупреждения для аудиофайлов в res/raw.
Похоже, проблема связана с тем, как MediaPlayer обрабатывает ресурсы в папке res/raw, но я понятия не имею, что такое «проблема» и почему она генерирует предупреждения MediaPlayer.
Есть ли причина вызвать сброс, а затем отпустить, я уверен, что вы просто хотите использовать выпуск? –
Для разных устройств это будет работать по-разному, так как медиаплеер - это всего лишь оболочка для собственных OEM-производителей, а родной сервис - все зависит от устройства. То же самое относится и к камере. даже если вы исправите управляемый код, чтобы удалить эти предупреждения, они могут появиться на другом устройстве. –
@RSenApps Спасибо за комментарий. Я хочу сказать, что у меня были некоторые проблемы в одно время, если я только что вызвал release() и раньше не вызывал reset(), но я не помню. В любом случае, я не думаю, что было бы больно вызвать reset() перед release(), так как reset() устанавливает MediaPlayer в неинициализированное состояние и release() освобождает ресурсы, связанные с объектом MediaPlayer. Однако вы правы, [руководство разработчика] (http://developer.android.com/guide/topics/media/mediaplayer.html#releaseplayer) указывает, что вам действительно нужно только освободить, а затем установить значение null. – Jason