スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ブログランキング・にほんブログ村へ

--.--.-- | スポンサー広告

Android開発 Widget

 jNTrainのウィジェット対応、結構時間がかかりました。 が、何とか必要最小限の機能は実装できたのでそろそろ公開したいなと思ってます。
 この開発がひと段落着けばjWezの開発も始めたいところなので、備忘録としてウィジェット開発時の個人的なポイントをメモメモ。

 Androidの基本的な開発に関してはググればいくらでも出てくるので助かるのですが、ビギナー向けなのか、スケルトンを動かしただけでOKとしているサイトも多く、ちょっと実践的な処理を行おうとすると詰まってしまうことも多かったのですね。 特にウィジェットの複数配置(でなおかつそれぞれ違う動作をさせたい場合)に関しては余り言及されてないような気がする。


■ウィジェットの構成

●AppWidgetProviderInfo
 ウィジェットのサイズ、レイアウトxmlの指定、更新間隔を定義しておく。
 サイズ違いのウィジェットを複数作成したい場合はこの定義を複数作成する。(サイズは74の倍数から2を引いたものを指定。)
 更新間隔は最小で30分なので、今回のjNTrainでは使用できなかった。 さらに、ここで更新を定義した場合、スリープも解除されてしまうらしいので、AlarmManagerを使用するほうが無難。 ウィジェットアプリでスリープからの強制復帰はしないでしょ。

●レイアウトxml
 通常のアプリ(Activity)を作成する場合と同様に作成。
 使用できるレイアウト、コントロール(ウィジェット)に制限があるので注意。

使えるのはこれだけらしい…

・LinearLayout
・FrameLayout
・RelativeLayout

・AnalogClock
・Button
・Chronometer
・ImageButton
・ImageView
・ProgressBar
・TextView
・ViewFlipper

●AppWidgetProviderクラス(を継承したクラス)
 ウィジェットの追加・更新・削除のイベントを受信する為のクラス。
 ここは通知を受け取るためのクラスなので、重たい処理などはServiceに任せるべき。 余り重い処理を行うとANR(Application Not Responding)が発生してしまう。
 ウィジェットには一意のID(WidgetID)がつけられるので、ウィジェット毎に違う表示を行いたい場合はonUpdateなどで引き渡されるIDをハンドリングする。

・public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)

 ウィジェットの更新時に呼ばれるメソッド。 ここでサービスを立ち上げることが多い?
 サービスは複数回数開始させてもインスタンスはひとつなので、毎回起動しても大丈夫かな。

 又、画面の定期更新の為のAlarmもここでセット。 これも何回セットしても上書きされるだけなので、毎回セットすることにする。
 ただし、WidgetID毎には独立してセットさせたいので、URLパラメータを使用して複数登録可能に。

・public void onDeleted(Context context, int[] appWidgetIds)

 ウィジェットの削除処理。
 ウィジェット毎に保持している情報をクリアする処理を入れる。
 jNTrainではAlarmのクリアと、個別に保持している情報の削除を行っている。

 最低この2つをオーバーライドして処理すればいいかな。

●マニフェスト
 マニフェストに記述することで、ウィジェットのホームへの配置の際にリストアップされる。
 以下の情報を記述
 ・名称
 ・AppWidgetProviderの派生クラス
 ・レイアウトxml
 ・移転とフィルタ

 今回、jNTrainでは大きさの異なるウィジェットを配置したかったので、AppWidgetProviderを派生したクラスをさらに派生させて表示内容の設定を各サイズ毎に変更した。

<receiver android:label="JNTrain 2x1" android:name=".widget.JNT_Widget2">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        <action android:name="android.appwidget.action." />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider" android:resource="@xml/app_widget_prov2" />
</receiver>
<service android:name=".widget.JNT_Widget$WidgetService"></service>

●Serviceクラス
 必須ではないけど、AppWidgetProviderでは重い処理をさせることはできないので、インテントを発行してサービス上で処理を行うほうがよい模様。
 複数ウィジェット配置を考慮する場合、更新対象のウィジェットを特定する必要があるので当然ウィジェットIDをインテントで引き渡す。

 jNTrainでは時刻表情報の読込み、保持、表示処理をここに組み込んだ。
 ただ、サービスは予期せず終了させられる事があるので、それを考慮する必要有。

■ウィジェットの表示更新
 通常のアプリのように直接Viewを取得できないのでRemoteViewsを使用する。

 Webで公開されている多くのサンプルでは、updateAppWidgetの第一引数にAppWidgetProviderの派生クラスのComponentNameを引き渡しているが、これだと複数配置した場合に全てのウィジェットが更新されてしまう。 jNTrainの場合、複数配置時に個別の情報を表示したいのでどうしたらいいのか迷いました。
 ウィジェット毎に個別に更新を行いたい場合は、第一引数にWidgetIDを引き渡すことでOK。 同じ挙動を行うウィジェットを複数配置することは稀だと思うので、WidgetIDを引き渡す方法のほうが重要っぽいんだけどなぁ。

// RemoteViewの取得
RemoteViews rv = new RemoteViews(getPackageName(), R.layout.widget);

// テキストの更新
rv.setTextViewText( R.id.xxxx,    "ABCDEF...");
// クリック時のインテント発行
rv.setOnClickPendingIntent(R.id.txtClick, pendingIntent);

// ビューへの反映
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(nWidgetID, rv);

■ウィジェットの表示更新その2
 どうやら動的な背景色の変更は、Android 2.1以前では正常に動作しない模様。
 2.2以降であれば、以下のコードで動くようなのですが…

rv.setInt(R.id.liner_layout, "setBackgroundColor", Color.RED);

 jNTrainでは一応1.6以降を対象としているので、いまさら非対象にはできず、以下のような方法をとることに。
 背景用にImageViewを配置して、背景用のイメージを差し替えることで対応。 jNTrainでは路線色の表示に使用したいので、Bitmapを作成して動的にピクセルを書き換えて対応しました。
 こういうバージョン毎に異なる現象はやめて欲しいなぁ。

■インテントの発行について
 AlarmManagerに登録、PendingIntentにセットするインテントは同じActivityに対してのものであれば、putExtra()でパラメータを変更していたとしても同一のものとしてみなされてしまう模様。

 AlarmManagerの場合は上書きされてしまうので、WidgetID毎にセットできない。 setData()でダミーのURL情報を付加する事で別のインテントとしてセットが可能。

 PendingIntentも同様。 又、PendingIntentでは2度目のセットの際には上書きしてくれない現象にぶち当たりました。(更新したかったので上書きされて欲しいパターン) 以下のように第4引数に「FLAG_UPDATE_CURRENT」をセットすることで、上書きされるようになりました。(始めに参考にしたサイトでは0を設定していたので、上書きされませんでした)

PendingIntent pendingIntent = PendingIntent.getActivity(this, nWidgetID, intent,
                                                                 PendingIntent.FLAG_UPDATE_CURRENT);

■設定の保存
 通常プレファレンスは、アプリに対してデフォルトのものを利用するようになっています。 ウィジェットは複数配置されるので、設定を丸ごとウィジェット毎に用意する必要が出てきました。
 SharedPreferencesはいままでデフォルトを使用してきましたが、ファイル名を直接指定するとことで別の設定ファイルを作成する事が可能なので、ウィジェットIDを付加したファイル名にして設定の個別化を実現しています。

// デフォルトのプレファレンス
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);

// ウィジェットごとのプレファレンス
SharedPreferences pref = getSharedPreferences( "Widget" + nWidgetID, MODE_PRIVATE);

■その他注意点
 再起動時、SDカードが有効になるタイミングが遅い為、アプリ自体をSDカードに入れておくと表示に失敗してしまう。 インストール先を本体のみにする考慮が必要。

 さらに、ウィジェットがSDカードのデータにアクセスする場合、SDカードにアクセスできるようになるまで待機する必要有。 jNTrainでは1分単位に更新されるので、リトライ処理は行わず、アクセスできたときのみ表示処理を行うことで対応。 jWezの場合は、更新周期が長めになるはずなので、ひと工夫いるかな。


 とりあえずは、これでjWezを作成する為に必要な技術情報は集まった感じ。 WindowsMobile版のときはJNTrainWMで勝手がわかってきたので、JWezWMは短期間で開発できたのですが、Android版のjWezはどうなるかな~。 WM版と大きく仕様を変更しなければ、それほど苦労はしないのではないかと思っているのですが。 そういや、JWezWMのアイコンの太陽って、ドロイド君に似てる気がする。





テーマ:スマートフォン - ジャンル:携帯電話・PHS

ブログランキング・にほんブログ村へ

2011.09.09 | Comments(0) | Trackback(0) | Android

«  | HOME |  »

FC2Ad

04 | 2017/05 [GO]| 06
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 - - -

最近の記事一覧 カテゴリ一覧 コメント一覧 トラックバック一覧 プロフィール リンク一覧
[カテゴリ]
WEBコンサルティング・ホームページ制作のバンブーウエイブ

ブログ内検索

ブロとも申請フォーム

この人とブロともになる

カスタム検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。