メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

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_ALLAPI 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の枝折

PackageManager | Android Developers / Android Developers)

Updated CustomTabsHelper#getPackageNameToUse / GitHub