AppShortcutsでNavigation Drawerを持ったActivityを起動するときの実装方法

今回、私の開発している[KyudoScoreBook](https://play.google.com/store/apps/details?id=com.bowyer.KyudoScoreBookSecond)でAppShortcutsを実装しました。
[KyudoScoreBook](https://play.google.com/store/apps/details?id=com.bowyer.KyudoScoreBookSecond)はGooglePlayStoreのようにNavigation Drawerを使っています。
Navigation Drawerから遷移できる基本機能の画面には、Navigation Drawerのメニューが選択された状態で表示するため、各画面はFragmentで切り替える実装を行っています。

<img src="https://qiita-image-store.s3.amazonaws.com/0/92349/acd80ed1-040d-e9cc-f285-4cf65df2bc6a.png" width=320/>

## AppShortcutsで実現したいこと

<img src="https://qiita-image-store.s3.amazonaws.com/0/92349/1b076b1d-f6e7-3a78-5af9-b5a11a5b7cf8.gif" width=320/>

AppShortcutsでは、Navigation Drawerのメニューに表示されている、記録、メモ一覧、グラフ、占いの4つのメニューを実装することにしました。
先程述べたように、記録のショートカットから起動された場合は、Navigation Drawerの記録が選択状態で起動してほしいです。
また、各画面は同じActivityで複数Fragmentを切り替える実装になっているので、AppShortcutsから起動するときは同じAcitivityを起動する必要があります。
[App ShortCuts](https://developer.android.com/guide/topics/ui/shortcuts.html)の説明や[googlesamples/android-AppShortcuts](https://github.com/googlesamples/android-AppShortcuts)には1つのショートカットのサンプルコードしかなく、困りました。


## Static ShortcutsのintentにExtraを詰め込む
AppShortcutsから同じActivityを起動し、異なるFragmentを表示させたいので、intentにExtraを詰め込んで起動する必要があります。
その場合以下のように`<intent>`タグで`<extra>`タグを囲みます。

```xml

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
  <shortcut
      android:enabled="true"
      android:icon="@drawable/ic_short_record"
      android:shortcutId="shortcut_record"
      android:shortcutLongLabel="@string/shortcut_record"
      android:shortcutShortLabel="@string/shortcut_record">
    <intent
        android:action="android.intent.action.VIEW"
        android:targetClass="com.bowyer.app.appshortcuts.ui.activity.MainActivity"
        android:targetPackage="com.bowyer.app.appshortcuts">
      <extra
          android:name="shortcut_id"
          android:value="RecordTabFragment"/>
    </intent>
    <categories android:name="android.shortcut.conversation"/>

  </shortcut>
  <shortcut
      android:enabled="true"
      android:icon="@drawable/ic_short_memo"
      android:shortcutId="shortcut_memos"
      android:shortcutLongLabel="@string/shortcut_memo_list"
      android:shortcutShortLabel="@string/shortcut_memo_list">
    <intent
        android:action="android.intent.action.VIEW"
        android:targetClass="com.bowyer.app.appshortcuts.ui.activity.MainActivity"
        android:targetPackage="com.bowyer.app.appshortcuts">
      <extra
          android:name="shortcut_id"
          android:value="MemoListFragment"/>
    </intent>

    <categories android:name="android.shortcut.conversation"/>
  </shortcut>
</shortcuts>
```

## どのAppShortcutsから起動されたかハンドリングする
AppShortcutsから起動したMainActivity側では、intentから`shortcut_id`のExtraを取得します。
私の場合、通常起動もMainActivityを使用するので、`shortcut_id`が存在しているかチェックしています。

```java

private static final String KEY_SHORTCUT_ID = "shortcut_id";
・・・
private void handleShortcutsAction() {
    boolean hasExtra = getIntent().hasExtra(KEY_SHORTCUT_ID);
    if (!hasExtra) {
      return;
    }
    String shortcutId = getIntent().getStringExtra(KEY_SHORTCUT_ID);
・・・
```

あとはこの`shortcutId`に応じた処理を記載します。

```java

    String shortcutId = getIntent().getStringExtra(KEY_SHORTCUT_ID);
    // 取得したshortcutIdからどのFragmentを起動するか決める
    Page page = Page.forMenuId(shortcutId);
    switch (page.getMenuId()) {
      case R.id.nav_record:
        pageChange(RecordTabFragment.newInstance());
        break;
      case R.id.nav_memo:
        pageChange(MemoListFragment.newInstance());
        break;
      case R.id.nav_chart:
        pageChange(ChartFragment.newInstance());
        break;
      case R.id.nav_notification:
        pageChange(NotificationFragment.newInstance());
        break;
      case R.id.nav_fortune:
        pageChange(FortuneFragment.newInstance());
        break;
    }
    // Navigation Drawerを選択状態にする
    navigationView.setCheckedItem(page.getMenuId());
```

GooglePlayStoreのようにNavigation Drawerで複数のFragmentを切り替えて使うようなアプリで、AppShortcutsを実装する場合は、参考にしてみてください。

## AppShortcutsのサンプルコード
今回リリースしたアプリの一部コードを切り出したものを公開してます。[KyudoScoreAppShortcuts](https://github.com/bowyer-app/KyudoScoreAppShortcuts)

このサンプルコードを提供してすぐはStatic ShortcutsのintentにExtraを詰め込む方法が分からなかったので、Dynamic Shortcutsを使って複数のIntentを作成するイケてない実装でした。
そのDynamic ShortcutsからStatic Shortcutsに実装をやり直したPRもありますので、よければ参考にしてください。
[Use static shortcuts with bundle extras](https://github.com/bowyer-app/KyudoScoreAppShortcuts/pull/2)

## 最後に
AppShortcutsはまだ情報が少なく、躓くことは多々あります。
私の公開したAppShortcutsの[サンプルコード](https://github.com/bowyer-app/KyudoScoreAppShortcuts)も、実装的にイケてない部分があります。
もしAppShortcutsの[サンプルコード](https://github.com/bowyer-app/KyudoScoreAppShortcuts)を見て、もっとこうした方が良いとかありましたらPRお願いします。