ウィジェット ホストを作成する

ほとんどの Android 搭載デバイスで利用可能な Android のホーム画面では、ユーザーはアプリ ウィジェット(またはウィジェット)を埋め込んでコンテンツにすばやくアクセスできます。ホーム画面の代替アプリまたは類似のアプリを作成する場合は、AppWidgetHost を実装して、ユーザーがウィジェットを埋め込むようにすることもできます。ほとんどのアプリでは、これは必要ありませんが、独自のホストを作成する場合は、ホストが暗黙的に同意している契約上の義務を理解することが重要です。

このページでは、カスタム AppWidgetHost の実装に伴う責任を中心に説明します。AppWidgetHost を実装する方法の具体例については、Android のホーム画面 LauncherAppWidgetHost のソースコードをご覧ください。

カスタム AppWidgetHost の実装に関連する主なクラスとコンセプトの概要は次のとおりです。

  • アプリ ウィジェット ホスト: AppWidgetHost は、UI にウィジェットを埋め込むアプリに対して、AppWidget サービスとやり取りします。AppWidgetHost には、ホスト自身のパッケージ内で一意の ID が必要です。この ID は、ホストのすべての使用で保持されます。ID は通常、アプリで割り当てるハードコードされた値です。

  • アプリ ウィジェット ID: 各ウィジェット インスタンスにバインディング時に一意の ID が割り当てられます。bindAppWidgetIdIfAllowed() と、後述のウィジェットのバインディングをご覧ください。ホストは allocateAppWidgetId() を使用して一意の ID を取得します。この ID は、ホストから削除されるまで、ウィジェットの存続期間中に保持されます。ウィジェットのサイズや場所など、ホスト固有の状態は、ホスティング パッケージで保持し、アプリ ウィジェット ID に関連付ける必要があります。

  • アプリ ウィジェットのホストビュー: AppWidgetHostView は、表示する必要があるときにウィジェットをラップするフレームと考えることができます。ホストによってウィジェットがインフレートされるたびに、ウィジェットは AppWidgetHostView に関連付けられます。

    • デフォルトでは、システムは AppWidgetHostView を作成しますが、ホストは AppWidgetHostView を拡張することで独自のサブクラスを作成できます。
    • Android 12(API レベル 31)以降、動的にオーバーロードされた色を処理するための setColorResources() メソッドと resetColorResources() メソッドが AppWidgetHostView に導入されています。ホストは、これらのメソッドの色を指定します。
  • オプション バンドル: AppWidgetHost はオプション バンドルを使用して、ウィジェットの表示方法(サイズ範囲のリストなど)と、ウィジェットがロック画面とホーム画面のどちらにあるかに関する情報を AppWidgetProvider に伝えます。この情報により、表示の方法と場所に基づいて、AppWidgetProvider でウィジェットのコンテンツと外観を調整できます。ウィジェットのバンドルを変更するには、updateAppWidgetOptions()updateAppWidgetSize() を使用します。どちらのメソッドも、AppWidgetProvider への onAppWidgetOptionsChanged() コールバックをトリガーします。

ウィジェットをバインドする

ユーザーがウィジェットをホストに追加すると、「バインディング」と呼ばれるプロセスが発生します。バインディングとは、特定のアプリ ウィジェット ID を特定のホストおよび特定の AppWidgetProvider に関連付けることです。

バインディング API を使用すると、ホストはバインディング用のカスタム UI を提供することもできます。このプロセスを使用するには、アプリはホストのマニフェストで BIND_APPWIDGET 権限を宣言する必要があります。

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

ただしこれで終わりではありません。実行時に、ユーザーがアプリに権限を明示的に付与して、ホストにウィジェットを追加できるようにする必要があります。ウィジェットを追加する権限がアプリにあるかどうかをテストするには、bindAppWidgetIdIfAllowed() メソッドを使用します。bindAppWidgetIdIfAllowed()false を返した場合、アプリはユーザーに権限の付与を促すダイアログを表示する必要があります。現在のウィジェットの追加については「許可」、今後のウィジェットの追加はすべて「常に許可」してください。

以下のスニペットは、このダイアログの表示方法に関する例です。

Kotlin

val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply {
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName)
    // This is the options bundle described in the preceding section.
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options)
}
startActivityForResult(intent, REQUEST_BIND_APPWIDGET)

Java

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
// This is the options bundle described in the preceding section.
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET);

ホストは、ユーザーが追加するウィジェットに設定が必要かどうかを確認する必要があります。詳細については、ユーザーがアプリ ウィジェットを構成できるようにするをご覧ください。

主催者の責任

AppWidgetProviderInfo メタデータを使用して、ウィジェットのさまざまな構成設定を指定できます。これらの構成オプションは、ウィジェット プロバイダに関連付けられた AppWidgetProviderInfo オブジェクトから取得できます(次のセクションで詳しく説明します)。

対象とする Android のバージョンに関係なく、すべてのホストに次の責任があります。

  • ウィジェットを追加する際に、前述のようにウィジェット ID を割り当てます。ウィジェットがホストから削除されたら、deleteAppWidgetId() を呼び出してウィジェット ID の割り当てを解除します。

  • ウィジェットを追加する際に、構成アクティビティを起動する必要があるかどうかを確認します。ウィジェットの構成アクティビティが存在し、かつ configuration_optional フラグと reconfigurable フラグの両方を指定して省略可能としてマークされていない場合、通常はホストがそれを起動する必要があります。詳しくは、構成アクティビティからウィジェットを更新するをご覧ください。これは、多くのウィジェットを表示する前に必要なステップです。

  • ウィジェットは、AppWidgetProviderInfo メタデータでデフォルトの幅と高さを指定します。これらの値は、セル単位で定義します。Android 12 以降、targetCellWidthtargetCellHeight が指定されている場合は、minWidthminHeight のみが指定されている場合は dps となります。ウィジェットのサイズ設定属性をご覧ください。

    ウィジェットは少なくともこの dps でレイアウトしてください。たとえば、多くのホストでは、アイコンやウィジェットがグリッドに配置されます。このシナリオでは、デフォルトでホストは minWidth 制約と minHeight 制約を満たす最小数のセルを使用してウィジェットを追加します。

前のセクションで説明した要件に加えて、特定のプラットフォーム バージョンには、ホストに新しい責任を割り当てる機能が導入されています。

対象とする Android バージョンに基づいてアプローチを決定する

Android 12

Android 12(API レベル 31)では、追加の List<SizeF> がバンドルされています。この中には、ウィジェット インスタンスがオプション バンドルで取得できる dp 単位の可能なサイズのリストが含まれています。指定するサイズの数はホストの実装によって異なります。ホストは通常、スマートフォン用に 2 つのサイズ(縦向きと横向き)と、折りたたみ式デバイス用に 4 つのサイズを提供します。

AppWidgetProviderRemoteViews に提供できる RemoteViews の数には MAX_INIT_VIEW_COUNT(16)の上限があります。AppWidgetProvider オブジェクトは RemoteViews オブジェクトを List<SizeF> の各サイズにマッピングするため、MAX_INIT_VIEW_COUNT を超えるサイズを指定しないでください。

Android 12 では、maxResizeWidth 属性と maxResizeHeight 属性も dps で導入されています。これらの属性のうち少なくとも 1 つを使用するウィジェットは、属性で指定されたサイズを超えないようにすることをおすすめします。

参考情報

  • 詳しくは、Glance リファレンス ドキュメントをご覧ください。