どうも。どっことです。今回はAndroidのウィジェット機能の実装方法について解説します。
ウィジェット機能
iOSと大きく違うところとして、Androidはウィジェット機能が挙げられると思います。アプリを起動しなくても、必要な機能だけ切り出したコンポーネントをホーム画面に配置することで、ユーザが必要なサービスにダイレクトにアクセスできるようになり、ユーザにより良い体験を提供することができます。
今回は、そんなウィジェット機能の実装方法について解説します。
実装手順
実装手順は以下の通りです。
- レイアウトファイルを用意する
- ウィジェット用の設定ファイルを追加する
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
に前項までに追加した設定ファイルとクラスを追記します。receivert
タグでSampleWidgetProvider
を追加し、Widgetのアップデート通知を受け取るための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)
}
}
まとめ
今回はAndroidのウィジェット機能の実装方法について解説しました。開発したアプリを利用してもらうための導線としてもウィジェットは機能するので、利用する際は参考にしていただけると幸いです。