Androidウィジェットを作る方法

※本ページにはプロモーション(広告)が含まれています。
Androidウィジェットを作る方法

ホーム画面に自分だけの便利なウィジェットを置きたいけどどこから始めればいいか悩んでいませんか。

この記事を読むとステップバイステップで実際に動くウィジェットが作れるようになり、レイアウトや更新処理のコツとつまずきの回避法まで学べます。

項目内容
独自コンテンツ1実際に手を動かすサンプルコードと導入手順を丁寧に解説します。
独自コンテンツ2ランタイムエラーや表示崩れなど実際につまずきやすい点とその直し方を紹介します。
独自コンテンツ3ウィジェットを魅力的に見せるレイアウトのコツとパフォーマンス改善のヒントを伝えます。

さあ小さなウィジェットを一緒に作って楽しく学んでいきましょう。

Android博士

最初は戸惑うのが当たり前です。まずは簡単なウィジェットを作って動かす喜びを味わってください。何度でも気軽に試して大丈夫ですよ。

目次

Androidでシンプルなホームウィジェットを作る方法

Androidでシンプルなホームウィジェットを作る方法

ホーム画面にちょっとした情報を置きたいときはシンプルなウィジェットが役に立ちます。必要最小限の仕組みで動くウィジェットを作って、徐々に機能を足していくやり方をやさしく解説します。

作るときの流れは大きく三つに分かれます。ウィジェットの情報を登録するファイルを作ること、見た目をres/layoutで作ること、AppWidgetProviderでRemoteViewsを作ってupdateAppWidgetすることです。

タップでアプリを開く処理や定期更新は後から足せます。まずは最小構成で動かしてから追加するのが安心して進められるコツです。

Android博士

最初は小さく動くウィジェットを作って動作確認をしてから機能を増やすと安心して進められますよ。

固定表示ウィジェットを作るパターン

固定表示ウィジェットを作るパターン

固定表示ウィジェットは更新頻度が低い情報に向いています。AppWidgetProviderのonUpdate内でRemoteViewsを作りAppWidgetManager.updateAppWidgetを呼ぶだけで簡単に動きます。

画像や重い処理は避けてリソースを節約しましょう。どうしても外部データが必要なら短いバックグラウンド処理で済ませるのが無難です。

AndroidManifest.xmlとres/xmlでウィジェット情報を登録する場所

項目内容
登録ファイルAndroidManifest.xmlにreceiverを宣言しmeta-dataでwidget情報を関連付けます。
ウィジェット定義res/xml/your_widget_info.xmlでサイズやinitialLayout,updatePeriodMillisなどを定義します。
配置場所manifestはアプリ直下にxmlファイルはres/xmlに置くとOSが正しく認識します。

res/layoutにwidget_layoutを作って見た目を決める場所

手順
レイアウトを作る

res/layout/widget_layout.xmlでLinearLayoutやConstraintLayoutを使って見た目を定義します。TextViewやImageViewにはidを付けてRemoteViewsから参照できるようにします。

手順
サイズを調整する

minWidthやminHeightをwidget_info.xmlと合わせて設定しホーム画面で崩れないようにします。wrap_contentなどは実機で確認すると安心です。

AppWidgetProviderのonUpdateでRemoteViewsを作ってupdateAppWidgetする手順

手順
onUpdateをオーバーライド

AppWidgetProviderのonUpdateでウィジェットID配列を受け取り更新処理を開始します。ここがウィジェット更新の起点になります。

手順
RemoteViewsを作る

RemoteViewsにレイアウトを指定してsetTextViewTextやsetImageViewResourceで表示内容を設定します。

手順
updateAppWidgetを呼ぶ

AppWidgetManager.updateAppWidgetにwidgetIdかComponentNameとRemoteViewsを渡して画面を更新します。

タップでアプリを開くパターン

タップでアプリを開くパターン

ウィジェットの一部をタップしてアプリを開くのはよくある使い方です。RemoteViews.setOnClickPendingIntentを使ってビューにPendingIntentを割り当てます。

通常はActivity起動用のIntentを作りPendingIntent.getActivityで包みます。SDKによってはFLAG_IMMUTABLEなどのフラグを付ける必要があるので忘れないでください。

RemoteViewsでPendingIntentを作りウィジェットのViewに設定する具体的な場所

手順
onUpdate内でIntentを作る

ウィジェット更新時のタイミングで開きたいActivityへのIntentを作成します。必要ならExtrasを付けて遷移情報を渡します。

手順
PendingIntentを生成する

PendingIntent.getActivityかgetBroadcastでIntentを包みFLAG_IMMUTABLEやFLAG_UPDATE_CURRENTを付けます。

手順
RemoteViewsに紐付ける

RemoteViews.setOnClickPendingIntentにViewのidとPendingIntentを渡してタップ時の挙動を設定します。

定期更新するパターン

定期更新するパターン

定期更新は天気やニュースのウィジェットでよく使います。AlarmManagerは扱いが簡単ですがDozeや省電力で遅延が発生しやすいのでWorkManagerを使う方が安定します。

WorkManagerならバッテリー制御に配慮した実行ができ互換性も高いです。更新間隔はシステム負荷とユーザー体験を両立するよう慎重に決めましょう。

AlarmManagerかWorkManagerで定期更新ジョブを登録するコードを置く場所

項目内容
ウィジェット設置時AppWidgetProvider.onEnabledでAlarmManagerやWorkManagerのジョブ登録を行うと設置と同時に開始できます。
アプリ起動時に一度だけApplicationクラスで初期登録するとアプリが起動したときに確実にスケジュールできます。
停止処理の配置AppWidgetProvider.onDisabledでジョブをキャンセルして不要な更新を止めてください。

更新ジョブ内でRemoteViewsを更新してupdateAppWidgetを呼ぶ手順

手順
RemoteViewsを作る

WorkerやBroadcastReceiver内でres/layoutのRemoteViewsを生成し表示内容をセットします。

手順
AppWidgetManagerを用意する

ContextからAppWidgetManagerを取得し対象のwidgetIdsかComponentNameを準備します。

手順
updateAppWidgetを呼ぶ

AppWidgetManager.updateAppWidgetでRemoteViewsを反映します。Workerの場合はResult.successを返して終了します。

Androidで設定画面やリストを含む応用ウィジェットの作り方

Androidで設定画面やリストを含む応用ウィジェットの作り方

設定画面やリストを含むウィジェットは少しだけ手順が増えますが、落ち着いて進めればきれいに作れます。ここでは設定Activityを使うパターン、コレクション(リスト)を表示するパターン、そしてリサイズ対応の基本を実例感覚でまとめます。

  • 設定画面付きウィジェット:configure属性でActivityを起動しウィジェットIDを受け取る方法。
  • コレクションウィジェット:RemoteViewsServiceとRemoteViewsFactoryでリストを渡す方法。
  • リサイズ対応:appwidget_infoでサイズを指定しonAppWidgetOptionsChangedでレイアウトを切替える方法。
Android博士

最初は情報が多く感じるかもしれませんが一つずつ実装して動かすと腑に落ちます。設定保存とリストの流れを分けて考えると楽になりますよ。

実装中はエミュレータか端末でウィジェットの追加削除を繰り返して挙動を確認するとバグを見つけやすくなります。

設定画面付きウィジェットの実装パターン

設定画面付きウィジェットの実装パターン

設定画面付きウィジェットはユーザーに細かいオプションを与えたいときに便利です。configureを使うとウィジェット追加時に設定Activityを起動できるので初期値の入力や認証などをスムーズに行えます。

実装パターンとしてはconfigureでActivityを呼び出し結果でウィジェットIDを受け取りSharedPreferencesなどに保存する流れが標準的です。ウィジェット削除時は保存した設定をonDeletedで消すことも忘れないでください。

AppWidgetProviderInfoにconfigureを指定して設定ActivityでウィジェットIDを受け取り保存する場所

項目内容
appwidget_infoのconfigure属性ウィジェット追加時に起動するActivityを指定します。
設定Activityで受け取る値起動IntentのextrasからAppWidgetManager.EXTRA_APPWIDGET_IDでウィジェットIDを受け取ります。
保存場所とキーSharedPreferencesにwidget_{widgetId}_keyのようにウィジェットIDを含めたキーで保存すると管理が楽になります。

コレクションウィジェットでリストを表示するパターン

コレクションウィジェットでリストを表示するパターン

リストを表示するコレクションウィジェットはホーム画面上でスクロールできるリストを実現できます。RemoteViewsServiceでServiceを実装しRemoteViewsFactoryで行ごとのRemoteViewsを作る流れが基本になります。

データ更新はAppWidgetManager.notifyAppWidgetViewDataChangedで行い、行ごとのクリックはsetPendingIntentTemplateとsetOnClickFillInIntentでハンドリングします。データ量が多い場合はバックグラウンドで読み込みキャッシュする工夫が役立ちます。

RemoteViewsServiceとRemoteViewsFactoryを実装してsetRemoteAdapterでリストを渡す場所

  1. RemoteViewsServiceを作成してmanifestに登録する。ServiceがRemoteViewsFactoryを返す仕様にする。
  2. RemoteViewsFactoryでgetViewAtなど必要なメソッドを実装し行ごとのRemoteViewsを返す。
  3. AppWidgetProviderでsetRemoteAdapterを呼び出してウィジェットのListViewにServiceを紐づける。

リサイズ対応の基本パターン

リサイズ対応の基本パターン

リサイズ対応は見た目を良くするために重要です。res/xmlのappwidget_infoでminWidthやminHeightを指定し、ホーム画面がサイズを変えたときにonAppWidgetOptionsChangedが呼ばれるのでそこで新しいサイズを取得してレイアウトを切替えます。

サイズ判定はピクセルからdpへの換算を忘れないでください。重い処理は避けて必要ならあらかじめ用意した複数レイアウトを切替えるだけにするとスムーズに動きます。

res/xmlのappwidget_infoでサイズを指定しonAppWidgetOptionsChangedでレイアウトを切替える手順

手順
appwidget_infoでサイズを指定

res/xml/appwidget_infoにminWidth,minHeight,minResizeWidth,minResizeHeightを設定してホーム画面にヒントを与えます。

手順
onAppWidgetOptionsChangedでサイズを取得

AppWidgetProviderで受け取ったoptionsBundleからAppWidgetManager.OPTION_APPWIDGET_MIN_WIDTHなどを読み取りレイアウトを決めます。

手順
選んだレイアウトで更新

選択したレイアウトでRemoteViewsを作りAppWidgetManager.updateAppWidgetでウィジェットを更新します。

よくある質問

よくある質問
ウィジェットをホーム画面に追加できない原因は何ですか

よくあるのはマニフェストやwidget-provider XMLの設定ミスです。AppWidgetProvider(ウィジェットを受け取るクラス)やandroid:providerの名前がずれていることが多いのでまずそこを確認してください。さらにAndroid12以降はPendingIntentのmutable/immutableフラグが必要になるので、その点も忘れずにチェックしてください。

ウィジェットの更新が期待どおりに動かないのはなぜですか

onUpdateで重い処理を行うとシステムに制限されやすいです。updatePeriodMillisは短すぎると意味がないことがあるので、定期処理はWorkManagerや適切なスケジューラを使うと安定します。頻繁更新が必要な場合はバッテリー制限も意識してください。

レイアウトがランチャーごとに崩れるときはどうすれば良いですか

RemoteViewsで使えるビューは限られているのでカスタムビューは避けてください。プレビューだけで安心せず、実機で複数のランチャーとリサイズ状態を確認してください。minWidthやminHeight、resizeModeを正しく設定すると見栄えが安定します。

タップしてもアクションが動かない場合のチェックポイントは何ですか

PendingIntentの作り方やフラグが原因になっていることが多いです。特にAndroid12以降はFLAG_IMMUTABLEやFLAG_MUTABLEの指定が必須になる場面があるので、IntentとPendingIntentを生成するときに適切なフラグを設定してください。同じrequestCodeで上書きされないように工夫するとハマりにくくなります。

テストやデバッグのコツを教えてください

ランチャーのキャッシュやOSの電池最適化で挙動が変わることがあるので、複数環境で必ず確認してください。adbコマンドでウィジェットを手早く更新したり、ウィジェットを一度削除して再追加することで状態をクリアすると原因が見つかりやすくなります。ログ出力とAppWidgetManagerの状態を確認すると問題の切り分けが楽になります。

まとめ

まとめ

ここまででシンプルなホームウィジェットを作る流れがつかめたはずです。レイアウトXMLの用意とAppWidgetProviderクラスの実装、appwidget-provider XMLの登録、クリック処理のためのPendingIntent設定、更新処理の設計を順に進めればホーム画面にウィジェットが出ます。RemoteViewsは操作が制限されるので複雑なレイアウトやカスタムビューは避けるか、必要ならActivityやサービスで補うと安定します。

更新はWorkManagerやJobSchedulerで行うとバッテリーに優しく、PendingIntentはAndroid12以降でFLAG_IMMUTABLEが必要な場面が多いのでフラグを忘れないようにしてください。appwidget-provider XMLのpreviewImageを設定しておくとウィジェット選択画面で見栄えが良くなります。まずは小さな機能で試しながら機能を増やし、最新端末(Android13以降)で実機確認する習慣をつけるとスムーズに進められます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次