MediaPlayer を使用してフォアグラウンド サービスでオーディオ ファイルを再生しています。ユーザーがフォアグラウンド サービスに関連付けられた通知をタップすると、次のようにインテントを使用してアクティビティを起動します。
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
このメソッドへの呼び出しがあります:
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)
次の方法で同じ例外を再作成できます。
- 通知をクリックしてアクティビティを開く
- 戻るボタンを押してアクティビティを閉じます。
- 通知をクリックして、アクティビティの新しいバージョンを開きます。
これにより、mediaController が何らかの形でリークしており、元の Activity インスタンスに表示されようとしていると考えるようになりました。ただし、mediaController はアクティビティの onCreate() 内でインスタンス化され、アクティビティ自体にのみ関連付けられているため、それが発生する理由は見つかりませんでした。(その後、アクティビティはコマンドをサービスに渡す処理を行います)。