ダイアログ表示時(Dialog#show)にBadTokenException
AndroidのService(サービス)メソッドを実行中に「通信中...」などと経過中のダイアログを表示したいなと思い、ProgressDialogを使用してみたのだが、
public boolean scrape(String siteurl, Bundle bundle) throws RemoteException { ProgressDialog dialog = new ProgressDialog(this); dialog.setIcon(android.R.drawable.ic_dialog_alert); dialog.setIndeterminate(true); dialog.setTitle("Webスクレイピングサービス"); dialog.setMessage("通信中です..."); try { dialog.show(); return WebScrapingService.this.doScrape(siteurl, bundle); } finally { dialog.dismiss(); } }
ProgressDialog#showメソッドを呼んだ時に見たことも無い例外が発生した。
-
- スタックトレースの一部
07-08 01:34:53.807: ERROR/AndroidRuntime(593): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application 07-08 01:34:53.807: ERROR/AndroidRuntime(593): at android.view.ViewRoot.setView(ViewRoot.java:509) 07-08 01:34:53.807: ERROR/AndroidRuntime(593): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177) 07-08 01:34:53.807: ERROR/AndroidRuntime(593): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 07-08 01:34:53.807: ERROR/AndroidRuntime(593): at android.app.Dialog.show(Dialog.java:241) :
ソースコードを追ってみると(ViewRoot#setView辺り)、どうやらサービスのコンテキスト(Context)でダイアログは表示できないらしい。(例外ではWindow階層に対象のViewを追加できないと怒られている)
解決策といっても、表示できないものは仕方が無い訳で、
1. ダイアログを表示するだけのActivityを用意して、サービスから呼び出す
2. 通知で良いのであればToastかNotificationを使用する
3. サービスは文字通り処理に徹し、GUIは全てActivity側でコントロールする(ダイアログもActivity側で表示する)
この中から選ぶしかなさそうだ。
1.は余計なActivityをわざわざ用意するのが嫌だし、2.は用途が限られる。やはりどう考えても3.だよな。