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

ショートカットを作成した後、アプリのライフサイクル全体でショートカットを管理することが必要になる場合があります。たとえば、ユーザーがショートカットを使用して特定のアクションを完了する頻度を判断して、アプリを最適化することが必要になる場合があります。また、アプリが古いアクションや欠落しているアクションを実行しないように、固定ショートカットを無効にすることもできます。会話で参照されるショートカットについては、使用状況を追跡して、ショートカットのランキングを改善するシグナルを提供することをおすすめします。

このページでは、これらの方法と、ショートカットを管理するその他の一般的な方法について説明します。

ショートカットの動作

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

ショートカットの表示

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

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

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

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

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

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

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

ランチャーにアプリのショートカットが表示される場合、次の順序で表示される必要があります。

  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_TASK と Intent.FLAG_ACTIVITY_CLEAR_TASK が設定されます。つまり、アプリの実行中に静的ショートカットが起動されると、アプリ内の既存のアクティビティがすべて破棄されます。この動作を回避するには、起動ブロック内で finish を呼び出すか、Compose コンテンツが設定される前に onCreate を呼び出すことで、トランポリン アクティビティ(別のアクティビティを開始する非表示のアクティビティ)を使用します。

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

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

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

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

動的ショートカットは、Intent フラグの任意のセットで公開できます。できれば、ショートカットのインテントで Intent.FLAG_ACTIVITY_SINGLE_TOP と Intent.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 を持つ既存のショートカットを更新できます。ただし、これらのメソッドは、指定されたショートカットのリストを動的ショートカットに変換しようとするため、動的でない固定ショートカットの更新には使用できません。

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

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

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

アプリは、システム ロケールの変更を示す 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.getShortcuts(this, ShortcutManagerCompat.FLAG_MATCH_PINNED).isNotEmpty()) {
                // Pinned shortcuts are restored. Use updateShortcuts() to make
                // sure they contain up-to-date information.
            }
        }
    }
    // ...
}