Невозможно исправить исключение MediaController.show ()

У меня есть аудиофайл, играющий в переднем плане с помощью MediaPlayer. Когда пользователь удаляет уведомление, связанное с службой переднего плана, я запускаю действие с использованием Intent следующим образом:

Intent audioPlayIntent = new Intent(context, AudioPlayActivity.class); audioPlayIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); audioPlayIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, audioPlayIntent, 0); 

Затем эта операция связывается с сервисом, чтобы показать MediaController пользователю.

Вот код привязки в службе:

 public class AudioPlayerServiceBinder extends Binder{ public AudioPlayerService getAudioService(){ return AudioPlayerService.this; //this class is declared in AudioPlayerService.java, so it has access to the Service instance. } } 

onStart в onStart меня есть вызов этого метода:

 private void bindAudioService() { Intent i = new Intent(this, AudioPlayerService.class); serviceConnection = new AudioServiceConnection(); bindService(i, serviceConnection, 0); } 

Я получаю исключение в строке mediaController.show (5000) ниже:

 private class AudioServiceConnection implements ServiceConnection{ AudioPlayerServiceBinder audioServiceBinder; @Override public void onServiceConnected(ComponentName name, IBinder serviceBinder) { serviceConnected = true; Log.i(TAG, "Connected to audio player service."); audioServiceBinder = ((AudioPlayerServiceBinder) serviceBinder); AudioPlayActivity.this.audioService = audioServiceBinder.getAudioService(); mediaController.show(5000); } 

Исключением является:

 android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? at android.view.ViewRoot.setView(ViewRoot.java:527) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) at android.view.Window$LocalWindowManager.addView(Window.java:424) at android.widget.MediaController.show(MediaController.java:304) at android.widget.MediaController.show(MediaController.java:249) at com.myapp.AudioPlayActivity$AudioServiceConnection.onServiceConnected(AudioPlayActivity.java:295) 

Я могу воссоздать одно и то же исключение:

  1. Нажатие на уведомление, чтобы открыть мероприятие
  2. Нажмите, чтобы закрыть активность.
  3. Нажмите на уведомление, чтобы открыть новую версию этого действия.

Это заставило меня поверить, что mediaController каким-то образом протекает и пытается показать себя в оригинальном экземпляре Activity. Я не мог найти причин, чтобы это произошло, поскольку mediaController создается внутри Activity's onCreate () и привязан к самой активности. (Затем действие обрабатывает передачу команд в службу).

Solutions Collecting From Web of "Невозможно исправить исключение MediaController.show ()"

Я думаю, что вы вызываете show() слишком рано, прежде чем предыдущая операция завершит жизненный цикл. BadTokenException можно избежать, задерживая вызов show() пока не будут вызваны все методы жизненного цикла. Вы можете опубликовать задерживаемый запуск для этого. Или вы можете попробовать следовать,

 if (!((Activity)your_context).isFinishing()) { mediaController.show(5000); } 

Исправлена ​​ошибка

У меня тоже была такая же проблема, и я исправил ее, сделав следующее:

 @Override public void onAttachedToWindow() { super.onAttachedToWindow(); try{ mediaController.show(0); }catch(Exception e){ e.printStackTrace(); } } 

Теперь это работает как шарм.

Я считаю, что проблема в этой строке.

 AudioPlayActivity.this.audioService = audioServiceBinder.getAudioService(); 

Вы можете посмотреть здесь подробности. Прочитайте все комментарии в нем, а не только ответ.

Внутри AudioPlayActivity's onCreate(Bundle) :

Вместо использования setContentView(int) макет (если вы уже это сделаете, пропустите вперед):

Объявить глобальную переменную View :

 View mContentView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContentView = getLayoutInflater().inflate(R.layout.your_activitys_layout, null); // initialize widgets Button b = (Button) mContentView.findViewById(...); .... .... // Finally setContentView(mContentView); } 

Измените AudioServiceConnection на следующее:

 private class AudioServiceConnection implements ServiceConnection{ AudioPlayerServiceBinder audioServiceBinder; @Override public void onServiceConnected(ComponentName name, IBinder serviceBinder) { serviceConnected = true; Log.i(TAG, "Connected to audio player service."); audioServiceBinder = ((AudioPlayerServiceBinder) serviceBinder); AudioPlayActivity.this.audioService = audioServiceBinder.getAudioService(); mContentView.post(new Runnable() { @Override public void run() { mediaController.show(5000); } }); } 

Это должно избавиться от WindowManager$BadTokenException .

Извиняюсь, если я полностью не понял этот вопрос.

Из приведенных выше шагов кажется, что onConnected() вызывается на пропущенном экземпляре предыдущей активности, созданной на шаге 1. Если услуга по требованию (связанная служба), вы должны привязать / развязать в onResume() / onPause() Соответственно.

Чтобы подтвердить утечку экземпляра, укажите:

 log.i("LEAKTEST", "Connected to instance " + this.toString()); 

Внутри onConnected() .

Теперь заново создайте сценарий и обратите внимание на идентификатор объекта в logcat, это будет похоже на «@ 1246464». Убедитесь, что он вызывается только один раз, на новый идентификатор объекта, каждый раз, когда начинается действие.