ウィジェットを実装する
ウィジェット機能を実装したい
実装手順
- レイアウトファイルを用意する
- ウィジェット用の設定ファイルを追加する
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