2015年3月21日土曜日

ExampleAppWidgetProvider.javaのコードバグ

多分すごくどうでもいいことですが気づいたので書いておきます(笑)

後で書くかもしれませんけど、元々はWidgetの挙動がどうしても気に入らないので動作をちょっと細かく見ていたところで気がつきました。

見ることのできるWidgetのコードをコンパイルして動かしたりしていて、やっぱりSDKのコードも見て見ないとダメかなとおもってみたところちょっとした違和感のあるコードが。



sdk/samples/android-22/legacy/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.javaのpackage com.example.android.apis.appwidget内のコード
    @Override
    public void onEnabled(Context context) {
        Log.d(TAG, "onEnabled");
        // When the first widget is created, register for the TIMEZONE_CHANGED and TIME_CHANGED
        // broadcasts.  We don't want to be listening for these if nobody has our widget active.
        // This setting is sticky across reboots, but that doesn't matter, because this will
        // be called after boot if there is a widget instance for this provider.
        PackageManager pm = context.getPackageManager();
        pm.setComponentEnabledSetting(
                new ComponentName("com.example.android.apis", ".appwidget.ExampleBroadcastReceiver"),
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    }

    @Override
    public void onDisabled(Context context) {
        // When the first widget is created, stop listening for the TIMEZONE_CHANGED and
        // TIME_CHANGED broadcasts.
        Log.d(TAG, "onDisabled");
        PackageManager pm = context.getPackageManager();
        pm.setComponentEnabledSetting(
                new ComponentName("com.example.android.apis", ".appwidget.ExampleBroadcastReceiver"),
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
    } 

やっていることはWidgetが使われ始めたらレシーバーを起こして受信待ちにさせて、使われなくなったらレシーバーを起こして受信待ちにさせて…あれ?(笑)
多分onDisabled内のPackageManager.COMPONENT_ENABLED_STATE_ENABLEDは
PackageManager.COMPONENT_ENABLED_STATE_DISABLEDなんじゃないでしょうかね?

API 16ですが、実際のエミュレータに入っているAPI DEMOのウィジェットをランチャーに貼り付けてタイムゾーンを変更するとログにExampleBroadcastReceiverのデバッグが表示されないのでよく解らなかったのですが、ウィジェットを削除したタイミングで以下のようなエラーが出ていました。
03-21 23:04:22.249    1589-1589/com.example.android.apis D/ExampleAppWidgetProvider﹕ onDeleted
03-21 23:04:22.259    1589-1589/com.example.android.apis D/ExampleAppWidgetProvider﹕ onDisabled
03-21 23:04:22.269    1004-1134/system_process W/PackageManager﹕ Failed setComponentEnabledSetting: component class .appwidget.ExampleBroadcastReceiver does not exist in com.example.android.apis
なるほど…ExampleBroadcastReceiverが削除されているか、パッキング時に無くなってるとかそんな感じな状態なんですかね?

仮に存在したとして、実際にExampleBroadcastReceiver.onReceiveが動いたとしてもExampleAppWidgetConfigure.loadAllTitlePrefsのメソッドはたぶん未実装なので、空のまま処理が継続しても、AppWidgetProvider. updateAppWidgetまで処理がたどり着かず。
もっと仮に loadAllTitlePrefsが実装されていたとしても、本来は空のままになりそう。万が一削除されたものがあたかも存在するとして扱われていたとしても、updateAppWidget内の

appWidgetManager.updateAppWidget(appWidgetId, views);
でエラーが出ればエラーになるぐらい?

現実はレシーバーの登録がされていない形になっているので、全く問題はなくなっちゃってるんでしょうね。

android-22のソースだけがおかしいのかと思いましたが、android-16のソースも同様でした。

0 件のコメント:

コメントを投稿