2013-10-01 2 views
2

Мое приложение работает нормально, но я получаю предупреждения 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.

+0

Есть ли причина вызвать сброс, а затем отпустить, я уверен, что вы просто хотите использовать выпуск? –

+1

Для разных устройств это будет работать по-разному, так как медиаплеер - это всего лишь оболочка для собственных OEM-производителей, а родной сервис - все зависит от устройства. То же самое относится и к камере. даже если вы исправите управляемый код, чтобы удалить эти предупреждения, они могут появиться на другом устройстве. –

+0

@RSenApps Спасибо за комментарий. Я хочу сказать, что у меня были некоторые проблемы в одно время, если я только что вызвал release() и раньше не вызывал reset(), но я не помню. В любом случае, я не думаю, что было бы больно вызвать reset() перед release(), так как reset() устанавливает MediaPlayer в неинициализированное состояние и release() освобождает ресурсы, связанные с объектом MediaPlayer. Однако вы правы, [руководство разработчика] (http://developer.android.com/guide/topics/media/mediaplayer.html#releaseplayer) указывает, что вам действительно нужно только освободить, а затем установить значение null. – Jason

ответ

1

Релиз медиа-плеера, когда он не используется mp.release();. Это решит вашу проблему.

Для примера.

mp.setOnCompletionListener(new OnCompletionListener() { 
    public void onCompletion(MediaPlayer mp) {  
     mp.release(); 
    } 
}); 
+0

остановкаAudio() уже делает. – Jason

Смежные вопросы