👻

Androidのショートカット実装 その2

2023/01/26に公開

今回は動的ショートカット

先日は、Androidのショートカット実装で静的ショートカットを実装した時の事を書いたので、今回は動的ショートカットについて書こうと思います。

動的ショートカットについて

「動的」ということで何となくイメージできると思いますが、事前にイメージしたのはショートカットに表示する内容を「動的」に変えられるようなイメージと思ってました。
公式サイトでは「コンテキスト依存のアプリのアクションに使用されます。コンテキスト依存のショートカットは、アプリ内でユーザーが行うアクションに合わせて調整されます。」と紹介されてます。
具体的な使用例として「ユーザーがレベルをクリアするたびにショートカットを更新する。」とあるので、アプリ内の任意のアクションに応じてショートカットを更新できるということですね。

動的ショートカットの実装

さて、静的ショートカットではxmlなどを用いて実装しましたが、今回の動的ショートカットはxmlは登場しません。
動的ショートカットはJetpackライブラリのShortcutManagerCompatを利用します。

動的ショートカットの追加はpushDynamicShortcut()を利用します。

 val shortcut = ShortcutInfoCompat.Builder(applicationContext, "id")
    .setShortLabel(formatted)
    .setIcon(IconCompat.createWithResource(applicationContext, R.drawable.ic_launcher_foreground))
    .setIntent(Intent.makeMainActivity(ComponentName(applicationContext, "com.example.vcs.MainActivity")))
    .build()
 ShortcutManagerCompat.pushDynamicShortcut(applicationContext, shortcut)

上記の例ではShortcutInfoCompat.Builder(context, String)のidを固定で指定してるので、pushDynamicShortcut()を実行するたびに同じショートカットの内容を更新します。
idを変化させればショートカットも複数作成する事ができました。

その他の設定の概要は以下の通りです。

  • setShortLabel -> ランチャーがショートカットをユーザーに表示するときに使用する
  • setIcon -> ランチャーがショートカットをユーザーに表示するときに使用する
  • setIntent -> ショートカットをタップした時に実行するIntent

なお、Intentを設定しないと「Shortcut must have an intent」で怒られます。

追加したショートカットを削除するには、removeDynamicShortcuts()またはremoveAllDynamicShortcuts()を使います。

idを指定して個別に削除するショーカットを指定する場合は「removeDynamicShortcuts()」、全てのショートカットを削除する場合は「removeAllDynamicShortcuts()」で可能です。

 ShortcutManagerCompat.removeDynamicShortcuts(applicationContext, listOf("id"))

 ShortcutManagerCompat.removeAllDynamicShortcuts(applicationContext)

Google Shortcuts Integration Library

詳しくはこちらに書いてありますが、オプションのJetpackライブラリです。

Google Shortcuts Integration Libraryを使用すると、Android サーフェス(ランチャーなど)と Google サーフェス(アシスタントなど)の両方に表示可能な動的ショートカットをプッシュできるようになります。

Google Shortcuts Integration Library は、アドレス可能な機能そのものは提供しません。このライブラリをアプリに追加することにより、ShortcutManagerCompat でプッシュしたショートカットを Google サーフェスが取り込めるようになります。

具体的な例としては以下のユースケースが紹介されてました。

メッセージ アプリなら、ユーザーが「山田さん」という相手にメッセージを送信した後、山田さんの連絡先の動的ショートカットをプッシュできます。その動的ショートカットがプッシュされた後は、ユーザーがアシスタントに「OK Google, 山田さんに ExampleApp でメッセージを送信」と言えば、アシスタントが ExampleApp を起動して山田さんにメッセージを送信するよう自動的に設定できるようになります。

Google Shortcuts Integration Libraryの追加方法は次の通りです。

  1. AndroidX ライブラリをサポートするためgradle.propertiesに以下を追加
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
  1. app/build.gradleにGoogle Shortcuts Integration Library と ShortcutManagerCompat の依存関係を追加
implementation "androidx.core:core:1.6.0"
implementation 'androidx.core:core-google-shortcuts:1.0.0'
  1. ShortcutManagerCompat の pushDynamicShortcut()を通じて動的ショートカットを追加する

サンプル実装

今回は、id固定で追加ボタンタップする度に時刻を取得し、ラベルの更新を行うような実装をしてみました。
また、削除ボタンで全てのショートカットを削除することも試しました。
※だいぶ省略してますが、JetpackComposeを利用してMainコンポーザブルに追加ボタンと削除ボタンがある前提です。

Main(
    onAddClick = {
        // 時間のみ
        val current = LocalDateTime.now()
        val formatter = DateTimeFormatter.ISO_TIME
        val formatted = current.format(formatter)

        val shortcut = ShortcutInfoCompat.Builder(applicationContext,"id")
	    .setShortLabel(formatted)
    	    .setIcon(IconCompat.createWithResource(applicationContext, R.drawable.ic_launcher_foreground))
            .setIntent(Intent.makeMainActivity(
                ComponentName(applicationContext, "com.example.vcs.MainActivity")))
	    .build()
        ShortcutManagerCompat.pushDynamicShortcut(applicationContext, shortcut)
    },
    onRemoveClick = {
        ShortcutManagerCompat.removeAllDynamicShortcuts(applicationContext)
    }
)


1回目の追加

2回目の追加(ラベルが変わっている)

最後に

ショートカット機能自体を活用してもらうには、まずはユーザーに認知してもらう必要があるので、そこが課題ではあります。
しかし、うまく利用すれば便利な機能だと感じたので、自プロダクトへの導入も含めて検討していきたい。

Discussion