ウィジェットを実装する
ウィジェット機能を実装したい
実装手順
- レイアウトファイルを用意する
- ウィジェット用の設定ファイルを追加する
AppWidgetProviderのサブクラスを作成するAndroidManifest.xmlに追記する
レイアウトを用意する
ウィジェットとして表示するレイアウトファイルを追加する。
通常のレイアウトファイルと同様、res/layoutフォルダに配置する。
ここではwidget_sample_view.xmlとする。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="Button"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
ウィジェット用の設定ファイルを追加する
アプリがウィジェット機能を備えていることをOS側に認識させるため、設定ファイルを作成する。
作成したファイルはres/xmlフォルダに配置する。(ここではwidget_provider.xmlとする)
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_sample_view"
android:minHeight="100dp"
android:minWidth="200dp"
android:updatePeriodMillis="1000000" >
</appwidget-provider>
AppWidgetProviderのサブクラスを作成する
AppWidgetProviderを継承したカスタムクラスを作成する。
今回はSampleWidgetProviderとして以下を作成。
class SampleWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context?,
appWidgetManager: AppWidgetManager?,
appWidgetIds: IntArray?
) {
context ?: return
val remoteViews = RemoteViews(context.packageName, R.layout.widget_sample_view)
val widget = ComponentName(context, SampleWidgetProvider::class.java)
appWidgetManager?.updateAppWidget(widget, remoteViews)
}
}
AndroidManifest.xmlに追記する
AndroidManifest.xmlに前項までに追加した設定ファイルとクラスを追記します。receiverタグでSampleWidgetProviderを追加し、ウィジェットのアップデート通知を受け取るためのintent-filter、そして前項で作成した設定ファイルをmeta-dataとしてタグ内に設定します。
<application
...>
<receiver android:name=".SampleWidgetProvider"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider" />
</receiver>
</application>
ここまで実装すれば、作成したウィジェットをホーム画面に配置することができます。
ウィジェット内のViewにクリックリスナーを設定したい
ウィジェット内にクリックリスナーを設定する場合、通常のクリックリスナーと異なり、実装できるのはIntentを発火させるだけ。
このIntentをActivityやService、BroadcastReceiverで受け取り、必要な処理を実施する。
画面を表示したいならActivity、画面を表示せず情報を更新したい場合などはServiceやBroadcastReceiverが通知先となる。
たとえば以下の例は、SampleActivityを起動する場合(何らかの画面を表示するケース)。
RemoteViews.setPendingIntentを使って、クリックリスナーを設定したいViewのIDと、
そのViewがタップされたときに発火するIntent(PendingIntent)を渡す。
class SampleWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context?,
appWidgetManager: AppWidgetManager?,
appWidgetIds: IntArray?
) {
context ?: return
val remoteViews = RemoteViews(context.packageName, R.layout.widget_sample_view)
// ボタンがタップされた時のintent(PendingIntent)を設定
remoteViews.setOnClickPendingIntent(R.id.button, createPendingIntent(context))
val widget = ComponentName(context, SampleWidgetProvider::class.java)
appWidgetManager?.updateAppWidget(widget, remoteViews)
}
private fun createPendingIntent(context: Context): PendingIntent {
// SampleActivityを通知先として指定
val intent = Intent(context, SampleActivity::class.java)
// 通知先がActivityなので、PendingIntent.getActivityでPendingIntentを生成。
// requestCodeやflagは任意の値
return PendingIntent.getActivity(context, 100, intent, PendingIntent.FLAG_IMMUTABLE)
}
}
参考
最終更新: 2025.9.7