ショートカットを管理する

ショートカットを作成した後、アプリの全期間にわたってショートカットを管理する必要が生じる場合があります。たとえば、アプリを最適化するため、ユーザーがショートカットを使用して特定のアクションを行う頻度を測定する場合などです。また、固定ショートカットを無効にして、アプリが古くなったアクションや存在しなくなったアクションを実行しないようにする場合もあります。会話で参照されるショートカットについては、使用状況をトラッキングして、ショートカットのランキングを改善するシグナルを提供することが望ましい場合があります。

このページでは、上記をはじめ、ショートカットを管理する一般的な方法について説明します。

ショートカットの動作

ここでは、ショートカットの動作(表示、表示順序、ランク)に関する一般的な情報について説明します。

ショートカットの表示

静的ショートカットと動的ショートカットは、ユーザーが特定の操作や音声コマンドを実行したときに、サポートされているランチャーまたはアシスタントに表示されます。サポートされているランチャーの場合、この操作はアプリのランチャー アイコンの長押しですが、他のランチャー アプリの場合は操作がこれと異なる場合があります。Google アシスタントを使用すると、ショートカットをアシスタント内に表示したり、ユーザーの音声コマンドで起動したりできます。

LauncherApps クラスは、ランチャー アプリがショートカットにアクセスするための API を提供します。

固定ショートカットはランチャー自体に表示されるため、常に表示されます。固定ショートカットは、以下の場合にのみ、ランチャーから削除されます。

  • ユーザーが削除した。
  • ショートカットに関連付けられているアプリがアンインストールされた。
  • ユーザーが [設定] > [アプリと通知] でアプリを選択し、[ストレージ] > [ストレージを消去] をタップしてアプリのデータを消去した。

共有ターゲットは、Android 共有シートのダイレクト シェアの行に表示される動的ショートカットのサブセットです。

Android Sharesheet
図 1. Android Sharesheet。ダイレクト シェア ターゲットは 1 行目に表示され、その後にランク付けされたアプリ、アプリリストが続きます。

ショートカットの表示順序

ランチャーがアプリのショートカットを表示する際は、次の順序で表示します。

  1. 静的ショートカット: isDeclaredInManifest() メソッドが true を返すショートカット。
  2. 動的ショートカット: ShortcutInfo.isDynamic() メソッドが true を返すショートカット。

同じ種類(静的または動的)の中では、ショートカットは ShortcutInfo.getRank に従って、ランクの昇順で並べられます。Google アシスタントは、ユーザーに表示する状況依存のショートカットを決定する際に、ショートカットのランクも考慮します。

ランクは、負ではない連続した整数です。静的ショートカットは、shortcuts.xml ファイルに表示される順にランク付けされます。動的ショートカットの場合、updateShortcuts(Context, List)addDynamicShortcuts(Context, List)pushDynamicShortcut(Context, ShortcutInfoCompat)、または setDynamicShortcuts(Context, List) を呼び出すと、既存のショートカットのランクを更新できます。

共有ターゲットの順序は、過去のユーザー履歴、リピート間隔、頻度、ランクのヒント、アプリの使用状況、共有ショートカットに関連付けられた会話に設定された優先度など、さまざまな要因に基づいて決まります。Sharing Shortcuts API を使用して作成された共有ターゲットは、Android 11 で非推奨となった ChooserTargetService によって生成された共有ターゲットよりも優先されます。Android 12 以降では、非推奨の ChooserTargetService によって生成された共有ターゲットは共有シートに表示されなくなります。

ほとんどのランチャーでは、最大 4 つのショートカットが表示されます。定義された静的ショートカットと動的ショートカットの組み合わせについて、ランチャーは最大で 2 つの静的ショートカットと 2 つの動的ショートカットを表示します。たとえば、4 つの静的ショートカットを定義し、3 つの動的ショートカットをプログラムで作成した場合、ランチャーには最初の 2 つの静的ショートカットと、ランク付けの高い 2 つの動的ショートカットが表示されます。

複数のインテントとアクティビティを管理する

ユーザーがショートカットを選択したときにアプリで複数のオペレーションを実行する場合は、連続したアクティビティをトリガーするように設定できます。そのためには、ショートカットの種類に応じて、複数のインテントを割り当てるか、アクティビティから別のアクティビティを開始するか、インテント フラグを設定するかのいずれかを行います。

アクティビティから別のアクティビティを開始する

静的ショートカットにカスタム インテント フラグを含めることはできません。静的ショートカットの最初のインテントには、常に Intent.FLAG_ACTIVITY_NEW_TASKIntent.FLAG_ACTIVITY_CLEAR_TASK を設定します。つまり、アプリが実行中の場合、静的ショートカットが起動されると、アプリ内の既存のアクティビティはすべて破棄されます。この動作を望まない場合は、トランポリン アクティビティ(別のアクティビティを開始する非表示のアクティビティ)を使用できます。これを行うには、起動ブロック内または onCreate で Compose コンテンツが設定される前に finish を呼び出します。

  1. AndroidManifest.xml file で、トランポリン アクティビティに android:taskAffinity="" 属性割り当てを含めます。

  2. ショートカットのリソース ファイルで、静的ショートカット内のインテントでトランポリン アクティビティを参照します。

トランポリン アクティビティの詳細については、アクティビティから別のアクティビティを開始するをご覧ください。

インテント フラグを設定する

動的ショートカットは、Intent フラグの任意のセットを使用して公開できます。ショートカットのインテントで Intent.FLAG_ACTIVITY_SINGLE_TOPIntent.FLAG_ACTIVITY_CLEAR_TOP の組み合わせを指定することが望ましいです。これにより、ComponentActivity がすでにアクティブな場合は、破棄されずにフォアグラウンドに移動して再利用されるため、単一アクティビティ アーキテクチャで onNewIntent() を介してショートカット イベントを適切に処理できます。

タスクとインテント フラグの詳細については、タスクとバックスタックをご覧ください。

ショートカットを更新する

各アプリのランチャー アイコンには、getMaxShortcutCountPerActivity が返す値に等しい数の静的ショートカットと動的ショートカットを組み合わせて含めることができます。アプリで作成できる固定ショートカットの数に制限はありません。

動的ショートカットが固定されている場合、パブリッシャーがそれを動的ショートカットとして削除しても、固定ショートカットは引き続き表示され、起動可能です。これにより、アプリは getMaxShortcutCountPerActivity の数を超えるショートカットを持つことができます。

次の例では、getMaxShortcutCountPerActivity から返される値が 4 であると想定しています。

  1. あるチャットアプリが、最新の 4 つのスレッド(c1、c2、c3、c4)を表す 4 つの動的ショートカットを公開します。
  2. ユーザーが 4 つのショートカットをすべて固定します。
  3. その後、ユーザーは追加のスレッド(c5、c6、c7)を 3 つ開始します。公開元アプリは動的ショートカットを再公開します。新しい動的ショートカット リストは c4、c5、c6、c7 になります。

アプリは 4 つを超える動的ショートカットを表示できないため、c1、c2、c3 を削除する必要があります。ただし、c1、c2、c3 は、依然としてユーザーがアクセスして起動できる固定ショートカットのままです。

これで、ユーザーは、公開元アプリのアクティビティにリンクする合計 7 つのショートカットを利用できるようになりました。この合計数には、最大数のショートカットと 3 つの固定ショートカットが両方とも含まれているからです。

  1. アプリは updateShortcuts(Context, List) を使用して、既存の 7 つのショートカットのいずれも更新できます。たとえば、チャット相手のアイコンが変更されたときに、このショートカット セットを更新できます。
  2. addDynamicShortcuts(Context, List) メソッドと setDynamicShortcuts(Context, List) メソッドを使用して、同じ ID を持つ既存のショートカットを更新できます。ただし、この 2 つは、指定されたリストのショートカットを動的ショートカットに変換しようとするため、動的でない固定ショートカットの更新には使用できません。

プッシュして Google アシスタントなどのアシスタント アプリに表示できるショートカットの数に制限はありません。アシスタント アプリで使用するショートカットを作成、更新するには、ShortcutManagerCompat Jetpack ライブラリの pushDynamicShortcut メソッドを使用します。また、Google アシスタントにダイナミック リンクを表示するには、Google Shortcuts Integration Library をアプリに追加します。

ショートカットの更新など、アプリのショートカットのガイドラインについては、ショートカットのベスト プラクティスをご覧ください。

システム ロケールの変更を処理する

アプリは、システム ロケールの変更を示す Intent.ACTION_LOCALE_CHANGED ブロードキャストを受信したときに、動的ショートカットと固定ショートカットを更新する必要があります。

ショートカットの使用状況をトラッキングする

静的ショートカットと動的ショートカットが表示される状況を判別するために、ランチャーはショートカットの使用履歴を調べます。静的ショートカットの場合、次のいずれかのイベントが発生した際に、reportShortcutUsed メソッドを呼び出してショートカットの ID を渡すことで、ユーザーがアプリ内で特定のアクションを完了したタイミングをトラッキングできます。

  • ユーザーが特定の ID のショートカットを選択した。
  • アプリ内で、ユーザーが同じショートカットに対応するアクションを手動で完了した。

動的ショートカットの使用状況をトラッキングするには、関連するイベントが発生した際に、pushDynamicShortcut メソッドを呼び出してショートカットの ID を渡します。このメソッドで動的ショートカットの使用状況をプッシュすると、Google アシスタントなどのアシスタント アプリが関連のショートカットをユーザーに提案できるようになります。pushDynamicShortcut メソッドを呼び出すことで使用状況が報告されるため、同じショートカットに対して reportShortcutUsed メソッドを呼び出さないでください。

会話関連のショートカットについては、送信メッセージと受信メッセージの使用状況を追跡することが重要です。詳しくは、ユーザーと会話に関するベスト プラクティスをご覧ください。

ショートカットを無効にする

アプリとそのユーザーはショートカットをデバイスのランチャーに固定できるため、固定ショートカットによって、アプリ内の古くなったアクションまたは存在しなくなったアクションにユーザーが誘導されることがあります。この状況に対処するには、disableShortcuts を呼び出して、ユーザーに選択させたくないショートカットを無効にします。これにより、指定したショートカットが静的ショートカットと動的ショートカットのリストから削除され、対応する固定ショートカットが無効になります。CharSequence をカスタムエラー メッセージとして受け入れる、このメソッドのオーバーロード版を使用することもできます。ユーザーが無効なショートカットを起動しようとすると、そのエラー メッセージが表示されます。

レート制限

setDynamicShortcuts, addDynamicShortcuts または updateShortcuts メソッドを使用する場合、バックグラウンド アプリ(フォアグラウンドで動作しているアクティビティまたはサービスがないアプリ)では、これらのメソッドを特定の回数しか呼び出せない可能性があります。これらのメソッドを呼び出すことができる回数の制限は、レート制限と呼ばれます。この機能は、ShortcutManagerCompat がデバイス リソースを過剰に消費することを防ぎます。

レート制限が有効になっている場合、isRateLimitingActive は true を返します。ただし、レート制限は特定のイベントでリセットされるため、バックグラウンド アプリであっても、レート制限に再び達するまで ShortcutManager メソッドを呼び出すことができます。これらのイベントには次のものがあります。

  • アプリがフォアグラウンドに復帰した。
  • システム ロケールが変更された。
  • ユーザーが通知に対してインライン返信アクションを実行した。

開発中またはテスト中にレート制限が発生した場合は、デバイスの設定から [開発者向けオプション] > [ShortcutManager のレート制限をリセット] を選択するか、adb で次のコマンドを入力します。

adb shell cmd shortcut reset-throttling [ --user your-user-id ]

バックアップと復元

アプリのマニフェスト ファイルに android:allowBackup="true" 属性の割り当てを含めると、ユーザーがデバイスを変更する際にアプリでバックアップと復元を行えるようになります。バックアップと復元をサポートする場合は、アプリのショートカットについて次の点に注意してください。

  • 静的ショートカットは自動的に再公開されますが、ユーザーが新しいデバイスにアプリを再インストールした場合に限られます。
  • 動的ショートカットはバックアップされないため、ユーザーが新しいデバイスでアプリを開いたときに動的ショートカットを再公開するには、アプリにそのためのロジックを組み込む必要があります。
  • 固定ショートカットはデバイスのランチャーに自動的に復元されますが、固定ショートカットに関連付けられたアイコンはバックアップされません。そのため、固定ショートカットの画像をアプリに保存して、新しいデバイスで簡単に復元できるようにする必要があります。

次のコード スニペットは、アプリの動的ショートカットを復元する最適な方法と、アプリの固定ショートカットが保持されたかどうかを確認する方法を示しています。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (ShortcutManagerCompat.getDynamicShortcuts(this).isEmpty()) {
            // Application restored. Re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.getPinnedShortcuts(this).isNotEmpty()) {
                // Pinned shortcuts are restored. Use updateShortcuts() to make
                // sure they contain up-to-date information.
            }

        }
    }
    // ...
}