Twidget 1.02

device-2012-10-21-091830

ついっぷる for AndroidなどをSDカードに移してもウィジェットから便利に呼び出したい……という欲求で作った Twidgetですが、SDカード上のアプリを呼び出す設定にしていると、再起動などがあった場合、SDカードのマウント完了のタイミングによっては、2x1の左側に表示するアプリアイコンを読み出し損なって、空っぽになってしまう問題が発覚。

この問題を修正した Ver 1.02をリリースしました。まあ、ユーザは四人しかいないので、あんまり問題ないかも知れませんが。

さて、対策をどうするか、考えたとき、ウィジェットにペリオディカルに処理を回して、アイコンを読み出してやるのが一番簡単なのですが、それをやってしまうと、わずかとはいえ、CPUも電池も消費します。このウィジェットは、ボタンにPending Intentを貼り付けるだけの、CPU、バッテリ消費ゼロがウリのひとつでもあるので、嬉しくありません。

幸い、AndroidはSDカードのマウントが完了すると、ACTION_MEDIA_MOUNTEDというブロードキャストが行われるので、これを拾うレシーバを作って、そこで、アイコンの読み出し直しをすればいいわけです。

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    if (Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction()))
    {
        // SD card mounted.
        ComponentName provider  = new ComponentName("jp.wildtree.android.widget.twidget",
                                                    "jp.wildtree.android.widget.twidget.TwidgetProvider");
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        int[] widgets = appWidgetManager.getAppWidgetIds(provider);
        for (int i = 0 ; i < widgets.length ; i++)
        {
            BitmapDrawable icon = (BitmapDrawable)TwidgetUtils.getAppIcon(context, widgets[i]);
            if (icon == null)
            {
                continue;
            }
            RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.main);
            Bitmap bitmap = icon.getBitmap();
            view.setImageViewBitmap(R.id.btnTwiApp, bitmap);
            appWidgetManager.updateAppWidget(widgets[i], view);
        }
    }
}

少々冗長ですが、アイコンを取得済みであろう、SDカード上にないアプリに関しても、再取得と画像の設定をしていますが、まあ、ウィジェットが数十とか数百とかあるってこともないでしょうから、許容範囲でしょう。厳密にはSDカード上のアプリかどうかをチェックして無駄を省くべきかも知れませんが、コードを膨らましてまでやることでもないようにも思います、メモリ貧乏ですから。

あとは、マニフェストファイルで、レシーバがACTION_MEDIA_MOUTEDを拾うように指定するだけです。

<receiver android:name=".TwidgetProvider" android:label="Twidget">
…………
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_MOUNTED"/>
    </intent-filter>
</receiver>