App Shortcutsとは?
Android 7.1から使えるようになった、アプリの特定の機能のショートカットをホームに作成できる仕組みです。
https://developer.android.com/guide/topics/ui/shortcuts.html
すでに実装例などがいくつか出ているので、ご存知の方も多いと思います。
この記事は?
App Shortcutsの実装方法はもうすでに紹介されているので、ここではApp Shortcutsに対応しているアプリの一覧と、具体的なショートカットを表示する方法を紹介したいと思います
ホームアプリを作成する
早速ですが、他アプリのショートカット情報を取得するには、ホームアプリとして設定されている必要があります。
https://developer.android.com/reference/android/content/pm/LauncherApps.html#hasShortcutHostPermission()
Only the default launcher can access the shortcut information.
Static Shortcutsならまだしも、Dynamic Shortcutsはユーザのアプリ使用状況などが反映されるので、プライバシーやセキュリティの観点から、このような仕様になっているのでしょう。
また、App Shortcutsに関する情報を取得するので、minSdkVersion
を25にする必要があります。
(普段の開発ではこんなに高くできないので何かワクワクしますね )
ホームアプリとして宣言する
まずは、AndroidManifest.xmlで、ホームアプリ宣言をします。
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</activity>
android.intent.category.HOME
を追加すればOKです。
(android.intent.category.LAUNCHER
はいらないかも)
ホームアプリとして設定する
アプリをインストールしたら、Settings > Apps > 右上の歯車アイコン > Home app から、このアプリをホームアプリとして設定します。
(ホームアプリを変更した場合でも、設定画面は通知バーから開けるので、そこから同じ手順で元に戻せます)
ショートカット情報を取得する
LauncherAppsの取得
LauncherApps launcherApps = (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
if (!launcherApps.hasShortcutHostPermission()) {
// ホームアプリとして設定されていない
return;
}
上述の通り、ホームアプリとして設定されていないと、何もできません。
アプリケーションを取得する
Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resolveInfoList) {
if (resolveInfo.activityInfo == null) continue;
ApplicationInfo applicationInfo = resolveInfo.activityInfo.applicationInfo;
// ...
}
ここまでは、従来のホームアプリと同じだと思います。
ショートカット情報を取得する
int queryFlags = LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC | LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED | LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST;
List<ShortcutInfo> shortcutInfoList = launcherApps.getShortcuts(new LauncherApps.ShortcutQuery().setPackage(applicationInfo.packageName).setQueryFlags(queryFlags), UserHandle.getUserHandleForUid(applicationInfo.uid));
for (ShortcutInfo shortcutInfo : shortcutInfoList) {
// ...
}
ShortcutQueryを適切に指定することで、全てのショートカットを取得してみます。
アイコンの取得
ショートカットのアイコンは、[getShortcutIconDrawable()](https://developer.android.com/reference/android/content/pm/LauncherApps.html#getShortcutIconDrawable(android.content.pm.ShortcutInfo, int))で取得します。
Drawable shortcutIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, getResources().getDisplayMetrics().densityDpi);
2つ目の引数であるdensityは、0にすればデフォルトっぽくなりそうでしたが、普通にクラッシュしたので上のようにしました。
また、[getShortcutIconDrawable()](https://developer.android.com/reference/android/content/pm/LauncherApps.html#getShortcutIconDrawable(android.content.pm.ShortcutInfo, int))と[getShortcutBadgedIconDrawable()](https://developer.android.com/reference/android/content/pm/LauncherApps.html#getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int))の違いはよく分かりませんでした。
アイコンの大きさがバラバラなのはよく分かりませんでした
ショートカットの起動
ShortcutInfoにgetIntent()やgetIntents()があるので、これをstartすればいいじゃんと思いましたが、どうやらそうではないようです
startActivity(shortcutInfo.getIntent()); // NG
startActivities(shortcutInfo.getIntents()); // NG
正しくは[startShortcut()](https://developer.android.com/reference/android/content/pm/LauncherApps.html#startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle))を使います。
launcherApps.startShortcut(shortcutInfo, null, null));
ただなぜか、設定アプリのWifiショートカットだけは、ActivityNotFoundException
で起動できませんでした
まとめ
App Shortcutsをホームアプリの側から調べてみました。
ホームアプリを作っている人はあまりいないと思いますが、通常のアプリでApp Shortcutsに対応しようとしている人の役にも立つかなと思います。
また、今回のソースコード全体は以下のリポジトリに置いてあります。
https://github.com/oxsoft/AppShortcutsViewer
何か間違いや意見などがありましたらコメントしていただけるとありがたいです