ウィジェットの更新に失敗する その2


また嵌ったのでメモ。


以前は画像サイズが大きいためにウィジェットの更新に失敗したが()、今回は、画像サイズはそれほど大きくない(更新できるときもある)のに、ある操作の流れの時だけ「!!! FAILED BINDER TRANSACTION !!!」が出て更新に失敗するケース。


状況は以下の通り。

  • ウィジェットをタップ→設定画面で設定変更→保存して閉じたときに更新処理を実行する(AppWidgetManager.updateAppWidget()をコール)が、ログに「!!! FAILED BINDER TRANSACTION !!!」が出てウィジェットが更新されない
  • 同じ設定画面からの保存でも、ウィジェットを新規追加する時の設定画面→保存→更新は必ず成功する(更新というか新規追加ですが)


対処方法は以下の通り。

  • 更新処理を新規作成したスレッドの中で処理する


なぜこれで直るのかは不明。
また、この現象は、ウチのIS05(Android 2.2)で確認しているが、ICONIA TAB A500(Android 3.1)では何故か再現しない。
フレームワークによっては、アプリのメインスレッドの延長からではウィジェットの更新に失敗したりするのかもしれない。


しかし、他の人が作ったウィジェット等でも、設定を保存して閉じても即座に設定反映されないものを割と見かける。しかも、Android 3.1の ICONIA TABの方でよく見るので、おそらく原因は上記とは違うものと思われる。この現象については、元々ウィジェットがそういう作りなのか(時計ウィジェットなどのように毎分ごとにしか更新してないとか、バッテリウィジェットのようにシステムからの通知が来ない限り更新されないとか)、それとも別の更新されない症状が存在するのか、気になるところではある。


あと OSを再起動すると表示が壊れるウィジェットもよく見るが、それはたぶんウィジェットアプリをSDにインストールしているからだと思われる。これは OS再起動時、SDがマウントされる前にシステムがウィジェットを表示しようとして失敗し、壊れた状態になってしまうように見える。原因がこのケースの場合は、アプリの管理画面でインストール先を本体の方に切り替えると症状が改善される。
この問題を防ぐには、ウィジェットアプリをSDにインストールしないようマーケットの説明文で促すか、アプリ自体を本体にしかインストールできないようにしておくしかない。私自身は、ウィジェットアプリはインストール先を本体固定にしておくのが無難だと思っている(Manifestファイルのmanifestタグに android:installLocation="internalOnly" を追加)。本体ストレージを圧迫するのでアプリをSDに入れたがるユーザは多いが、再起動するたびにユーザにウィジェットを再配置させるよりは良い気がする。ただしウィジェットはそのアプリの性質上サイズが大きくなりがちなので、本当はSDに入れても正しく動くようにシステムを直して欲しいところ。ICE CREAM SANDWICH はその辺どうなんだろう?