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

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

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

ショートカットの動作

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

ショートカットの表示

静的ショートカットと動的ショートカットは、ユーザーが特定の操作や音声コマンドを行うと、サポートされているランチャーまたはアシスタントに表示されます。サポートされているランチャーでは、アプリのランチャー アイコンを長押しする操作ですが、他のランチャー アプリでは異なる操作になる場合があります。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) を呼び出すと、既存のショートカットのランクを更新できます。

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

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

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

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

複数のインテントを割り当てる

ShortcutInfoCompat.Builder でショートカットを作成する場合、setIntent() の代わりに setIntents() を使用できます。setIntents() を呼び出すと、ユーザーがショートカットを選択したときにアプリ内で複数のアクティビティを起動し、リストの最後のアクティビティを除くすべてをバックスタックに配置できます。その後、ユーザーがデバイスの [戻る] ボタンをタップすると、デバイスのランチャーに戻る代わりに、アプリに別のアクティビティが表示されます。

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

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

  1. AndroidManifest.xml ファイルで、トランポリン アクティビティに属性割り当て android:taskAffinity="" を含めます。
  2. ショートカットのリソース ファイルで、静的ショートカット内のインテントでトランポリン アクティビティを参照します。

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

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

動的ショートカットは、任意の Intent フラグのセットを使用して公開できます。可能であれば、Intent.FLAG_ACTIVITY_CLEAR_TASK を他のフラグと一緒に指定します。そうしないと、アプリの実行中に別のタスクを開始しようとすると、ターゲット アクティビティが表示されないことがあります。

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

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

各アプリのランチャー アイコンには、getMaxShortcutCountPerActivity が返す値と同じ数の静的ショートカットと動的ショートカットを合計した数だけ含めることができます。1 つのアプリが作成できる固定ショートカットの数に制限はありません。

動的ショートカットが固定されている場合、パブリッシャーが動的ショートカットとして削除した場合でも、固定されたショートカットは引き続き表示され、起動できます。これにより、アプリに 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 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 属性の割り当てを含めると、デバイスの変更時にユーザーがアプリでバックアップと復元の操作を実行できるようになります。バックアップと復元をサポートする場合は、アプリのショートカットについて次の点に注意してください。

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

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

Kotlin

class MyMainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (ShortcutManagerCompat.dynamicShortcuts.size == 0) {
            // Application restored. Re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.pinnedShortcuts.size > 0) {
                // Pinned shortcuts are restored. Use updateShortcuts() to make
                // sure they contain up-to-date information.
            }

        }
    }
    // ...
}

Java

public class MainActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (ShortcutManagerCompat.getDynamicShortcuts().size() == 0) {
            // Application restored. Re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.getPinnedShortcuts().size() > 0) {
                // Pinned shortcuts are restored. Use pdateShortcuts() to make
                // sure they contain up-to-date information.
            }
        }
    }
    // ...
}