MashwmallowでqueryIntentActivitiesの挙動が変わってた
Chrome Custom Tabsを使っていて、公式のサンプルにあるCustomTabsHelperを流用していたのですが、Mashwmallowでうまく動かないことがありました。
CustomTabsHelper内で、PackageManager#queryIntentActivities
を使っているのですが、その挙動がMashwmallow以前と以降で異なっていたのが原因でした。
どう変わったのかと、回避方法を紹介します。
Mashwmallow以前
次のように呼ぶことで、引数のIntentに対応できるActivityを持つアプリを取得できます。
PackageManager pm = this.getPackageManager(); List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
queryIntentActivities(Intent intent, int flags)
の第二引数のflags
には、PackageManager.MATCH_DEFAULT_ONLY
を指定します。こうすることで、 android.intent.category.DEFAULT
を持つActivityのみを反応させることができます。
どんなIntentかにもよりますが、次のようにするとブラウザ系のアプリの一覧が表示されると思います。
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
Mashwmallow以降
Mashwmallow以降で同じように呼ぶと、そのIntentに対応するActivityを「常時」で規定で開く設定にしている場合、結果が変わります。
結果は、 規定で開く設定にしているActivityしか返さない ようになります。
規定で開くの設定を解除すると、Mashwmallow以前と同じになります。
Mashwmallow以前と等しい挙動で取得するためにはqueryIntentActivities(Intent intent, int flags)
の第二引数のflags
を、PackageManager.MATCH_ALL
を指定します。
PackageManager pm = this.getPackageManager(); List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(intent, PackageManager.MATCH_ALL);
PackageManager.MATCH_ALL
はAPI Level 23から追加されたflagです。
Querying flag: if set and if the platform is doing any filtering of the results, then the filtering will not happen.
とあるので、フィルタリングされたくない時に使うようです。
バージョン対応
共存させるには、バージョンでflags
を切り替えれば良いです。
例えば次のような感じです。
int flag; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { flag = PackageManager.MATCH_ALL; } else { flag = PackageManager.MATCH_DEFAULT_ONLY; } ResolveInfo info = pm.resolveActivity(intent, flag);
CustomTabsHelperの場合は、公式のサンプルにPullRequestがきてるので、それに習うといいと思います。
まとめ
Mashwmallow以降以前で挙動が変わる場合があるので、バージョンを見てflagsを切り替えましょう。
しかし、API Level 23未満で、PackageManager.MATCH_ALL
を指定したところ、クラッシュも発生せず同じように取得できていたので、最悪PackageManager.MATCH_ALL
のほうだけ使っておけば良いのかもしれません。。
参考
Chrome Custom Tabs / Google Chrome
GoogleChrome/custom-tabs-client / GitHub
custom-tabs-client/CustomTabsHelper.java / GitHub
Intent Resolving in Android M / Medium
Android:IntentFilterにDEFAULT_CATEGORYが必要な理由 / Yukiの枝折