4

I cannot seem to fix this problem:

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

I have an application which has an activity hosting a fragment which has a MediaController. The activity is bound to a Service hosting the mediaplayer. What I want to be able to do is start a song playing from activity A, show the mediacontroller. Then leave activity A and enter activity B reconnect to the service and if the audio is still playing show the MediaController in activity B. I keep getting the error above no matter what I do. Activity A and B are the same just different instances of the same activity. Let me know if you need to see any other code.

 private ServiceConnection callConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected( ComponentName name, IBinder service ) {
        Log.d("LEAKTEST", "Connected to instance " + this.toString());
        AudioService.MusicBinder binder = ( AudioService.MusicBinder ) service;
        callService = binder.getService();
        callService.setPreparedCallback( SpeciesDetailsFragment.this );
        callService.setList( callList );
        callService.setSpeciesId( getSpeciesId() );
        if ( callService.isPng() ) {
            setController();
            showController();
        }
        musicBound = true;
    }

    @Override
    public void onServiceDisconnected( ComponentName name ) {
        musicBound = false;
    }
};

private void setController() {
    if ( controller == null ) {
        controller = new CallController( getActivity() );
    }
    controller.setPrevNextListeners( new View.OnClickListener() {
        @Override
        public void onClick( View v ) {
            playNext();
        }
    }, new View.OnClickListener() {
        @Override
        public void onClick( View v ) {
            playPrev();
        }
    } );
    controller.setMediaPlayer( this );
    controller.setAnchorView( rootView );
}

private void showController(){
    controller.show(0);
    controller.setEnabled( true );
}

   @Override
public void onPause() {
    controller.hide();
    loadingDialog.hide();
    super.onPause();
}

@Override
public void onStop() {
    controller.hide();
    controller = null;
    // Unbind from the service
    if ( musicBound ) {
        getActivity().unbindService( callConnection );
        musicBound = false;
    }
    super.onStop();
}

Full Stacktrace:

06-03 19:38:11.986  17417-17417/com.myname.appname.core E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.myname.appname.core, PID: 17417
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:536)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
        at android.widget.MediaController.show(MediaController.java:346)
        at com.myname.appname.core.details.SpeciesDetailsFragment.showController(SpeciesDetailsFragment.java:354)
        at com.myname.appname.core.details.SpeciesDetailsFragment.access$700(SpeciesDetailsFragment.java:49)
        at com.myname.appname.core.details.SpeciesDetailsFragment$6.onServiceConnected(SpeciesDetailsFragment.java:382)
        at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1117)
        at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1134)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5144)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:611)
        at dalvik.system.NativeStart.main(Native Method)

Thanks, Nathan

Nath5
  • 1,665
  • 5
  • 28
  • 46

1 Answers1

2

According to the call stack, the showController() method is being called at an unappropriate time -- either before the Fragment is ready, or else after it's been torn down.

For the first case, you should check where you're calling bindService() from the Fragment class. onActivityCreated() would be the best place, since it implies that the Activity is completely ready. The Fragment's constructor, or similar places, would not work correctly.

For the second case, you should make sure that any onServiceConnected() arriving while the Fragment is being torn down doesn't cause a problem. The easiest way would probably be to set a flag in onStop() and check for it before trying to show the controller.

As an aside, it appears that you're passing the fragment object to the service:

callService.setPreparedCallback(SpeciesDetailsFragment.this);

That's not a good idea. A service and and UI component such as a fragment have completely separate lifecycles. This could be related to the problem, or not, but I would suggest you try to do this differently.

matiash
  • 54,791
  • 16
  • 125
  • 154