アプリ ウィジェットは構成可能です。たとえば、時計ウィジェットでは、表示するタイムゾーンをユーザーが構成できます。
ユーザーがウィジェットの設定を構成できるようにするには、ウィジェットの設定 Activity
を作成します。このアクティビティは、指定した構成オプションに応じて、ウィジェットの作成時またはそれ以降に、アプリ ウィジェット ホストによって自動的に起動します。
構成アクティビティを宣言する
Android マニフェスト ファイルで、構成アクティビティを通常のアクティビティとして宣言します。アプリ ウィジェット ホストは ACTION_APPWIDGET_CONFIGURE
アクションで起動するため、アクティビティはこのインテントを受け入れる必要があります。次に例を示します。
<activity android:name=".ExampleAppWidgetConfigurationActivity">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
AppWidgetProviderInfo.xml
ファイルで android:configure
属性を使用してアクティビティを宣言します。詳しくは、このファイルの宣言をご覧ください。以下に、構成アクティビティを宣言する方法の例を示します。
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
...
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
... >
</appwidget-provider>
ランチャーはパッケージ スコープの外部からアクティビティを参照するため、アクティビティは完全修飾名前空間で宣言されます。
構成アクティビティを開始するために必要なものはこれだけです。次に、実際のアクティビティを実装する必要があります。
構成アクティビティを実装する
アクティビティを実装する際は、次の 2 つの重要な点に留意してください。
- アプリ ウィジェット ホストは構成アクティビティを呼び出し、構成アクティビティは常に結果を返す必要があります。結果には、アクティビティを起動したインテントから渡されたアプリ ウィジェット ID(
EXTRA_APPWIDGET_ID
としてインテント エクストラに保存されている)が含まれている必要があります。 - システムは、構成アクティビティの起動時に
ACTION_APPWIDGET_UPDATE
ブロードキャストを送信しません。つまり、ウィジェットの作成時にonUpdate()
メソッドを呼び出しません。ウィジェットを初めて作成するときにAppWidgetManager
から更新をリクエストするのは、構成アクティビティの役割です。ただし、onUpdate()
は後続の更新で呼び出されます。初回のみスキップされます。
構成から結果を返してウィジェットを更新する方法の例については、次のセクションのコード スニペットをご覧ください。
構成アクティビティからウィジェットを更新する
ウィジェットが構成アクティビティを使用する場合、構成の完了時にウィジェットを更新するのはアクティビティの役割です。そのためには、AppWidgetManager
から直接アップデートをリクエストします。
ウィジェットを適切に更新して構成アクティビティを閉じる手順の概要は次のとおりです。
アクティビティを起動したインテントからアプリ ウィジェット ID を取得します。
Kotlin
val appWidgetId = intent?.extras?.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID ) ?: AppWidgetManager.INVALID_APPWIDGET_ID
Java
Intent intent = getIntent(); Bundle extras = intent.getExtras(); int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; if (extras != null) { appWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); }
アクティビティの結果を
RESULT_CANCELED
に設定します。これにより、ユーザーがアプリの終了前にアクティビティを終了した場合、設定がキャンセルされたことと、ホストがウィジェットを追加しないことをアプリ ウィジェット ホストに通知します。
Kotlin
val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) setResult(Activity.RESULT_CANCELED, resultValue)
Java
int resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); setResult(Activity.RESULT_CANCELED, resultValue);
ユーザーの設定に応じてウィジェットを設定します。
構成が完了したら、
getInstance(Context)
を呼び出してAppWidgetManager
のインスタンスを取得します。Kotlin
val appWidgetManager = AppWidgetManager.getInstance(context)
Java
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
updateAppWidget(int,RemoteViews)
を呼び出して、ウィジェットをRemoteViews
レイアウトで更新します。Kotlin
val views = RemoteViews(context.packageName, R.layout.example_appwidget) appWidgetManager.updateAppWidget(appWidgetId, views)
Java
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget); appWidgetManager.updateAppWidget(appWidgetId, views);
戻りインテントを作成し、アクティビティの結果を設定して、アクティビティを終了します。
Kotlin
val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) setResult(Activity.RESULT_OK, resultValue) finish()
Java
Intent resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); setResult(RESULT_OK, resultValue); finish();
例については、GitHub の ListWidgetConfigureActivity.kt
サンプルクラスをご覧ください。
ウィジェットの構成オプション
デフォルトでは、アプリ ウィジェット ホストは、ユーザーがホーム画面にウィジェットを追加した直後に、構成アクティビティを 1 回だけ起動します。ただし、ユーザーが既存のウィジェットを再構成できるようにするオプションや、デフォルトのウィジェット構成を指定することでウィジェットの初期構成をスキップできるようにするオプションを指定することもできます。
配置したウィジェットをユーザーが再設定できるようにする
ユーザーが既存のウィジェットを再構成できるようにするには、appwidget-provider
の widgetFeatures
属性に reconfigurable
フラグを指定します。詳しくは、AppWidgetProviderInfo.xml
ファイルを宣言するためのガイドをご覧ください。次に例を示します。
<appwidget-provider
android:configure="com.myapp.ExampleAppWidgetConfigurationActivity"
android:widgetFeatures="reconfigurable">
</appwidget-provider>
ウィジェットを再構成するには、ウィジェットを長押しし、[Reconfigure] ボタン(図 1 の 1)をタップします。
ウィジェットのデフォルト設定を使用する
ユーザーが最初の構成手順をスキップできるようにすることで、よりシームレスなウィジェット エクスペリエンスを実現できます。これを行うには、widgetFeatures
フィールドに configuration_optional
フラグと reconfigurable
フラグの両方を指定します。これにより、ユーザーがウィジェットを追加した後の設定アクティビティの起動が省略されます前述のとおり、ユーザーは後でウィジェットを再構成できます。たとえば、時計ウィジェットは初期設定をバイパスして、デフォルトでデバイスのタイムゾーンを表示できます。
構成アクティビティを変更可能とオプションの両方としてマークする方法の例を以下に示します。
<appwidget-provider
android:configure="com.myapp.ExampleAppWidgetConfigurationActivity"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
ユーザーがウィジェットを固定できるようにする
Android 8.0(API レベル 26)以降を搭載しているデバイスでは、ユーザーが固定ショートカットを作成できるランチャーにより、ホーム画面にウィジェットを固定することもできます。次の動画に示すように、固定ショートカットと同様に、これらの固定ウィジェットを使用すると、ユーザーはアプリ内の特定のタスクにアクセスでき、アプリから直接ホーム画面に追加できます。
アプリで、サポートされているランチャーにウィジェットを固定するリクエストを作成するには、次の手順を行います。
アプリのマニフェスト ファイルでウィジェットを宣言していることを確認します。
次のコード スニペットに示すように、
requestPinAppWidget()
メソッドを呼び出します。
Kotlin
val appWidgetManager = AppWidgetManager.getInstance(context) val myProvider = ComponentName(context, ExampleAppWidgetProvider::class.java) if (appWidgetManager.isRequestPinAppWidgetSupported()) { // Create the PendingIntent object only if your app needs to be notified // when the user chooses to pin the widget. Note that if the pinning // operation fails, your app isn't notified. This callback receives the ID // of the newly pinned widget (EXTRA_APPWIDGET_ID). val successCallback = PendingIntent.getBroadcast( /* context = */ context, /* requestCode = */ 0, /* intent = */ Intent(...), /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT) appWidgetManager.requestPinAppWidget(myProvider, null, successCallback) }
Java
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); ComponentName myProvider = new ComponentName(context, ExampleAppWidgetProvider.class); if (appWidgetManager.isRequestPinAppWidgetSupported()) { // Create the PendingIntent object only if your app needs to be notified // when the user chooses to pin the widget. Note that if the pinning // operation fails, your app isn't notified. This callback receives the ID // of the newly pinned widget (EXTRA_APPWIDGET_ID). PendingIntent successCallback = PendingIntent.getBroadcast( /* context = */ context, /* requestCode = */ 0, /* intent = */ new Intent(...), /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT); appWidgetManager.requestPinAppWidget(myProvider, null, successCallback); }