在Android上获取首选/默认应用程序

我正在尝试获取给定Intent的默认/首选应用程序。 例如,当用户安装第二个Web浏览器,然后尝试打开一个URL,他或她会得到这样一个对话框:

默认浏览器选择器

如果用户然后select了“ 默认使用此操作”选项,则当按下URL时,对话框不再打开。

我正在处理一个应该知道这个默认首选应用程序/动作是什么的应用程序。 我该怎么做呢? 我目前使用下面的代码,但getPreferredPackage不会返回任何内容:

 Intent i = (new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com")); PackageManager pm = context.getPackageManager(); final List<ResolveInfo> list = pm.queryIntentActivities(i, 0); IntentFilter ifilter = new IntentFilter(i.getAction()); if (i.getCategories() != null) { for(String category : i.getCategories()) { ifilter.addCategory(category); } } List<IntentFilter> filters = new ArrayList<IntentFilter>(); filters.add(ifilter); List<ComponentName> preferredActivities = new ArrayList<ComponentName>(); pm.getPreferredActivities(filters, preferredActivities, null); for (ComponentName activity : preferredActivities) { for (ResolveInfo rinfo : list) { if (rinfo.activityInfo.applicationInfo.packageName.equals(activity.getPackageName())) { try { final PackageInfo pi = pm.getPackageInfo(activity.getPackageName(), 0); Toast.makeText(context, pm.getApplicationLabel(pi.applicationInfo), Toast.LENGTH_SHORT).show(); } } catch (NameNotFoundException e) { e.printStackTrace(); } } } 

我究竟做错了什么? 这是否是正确的方法?

Solutions Collecting From Web of "在Android上获取首选/默认应用程序"

那么,解决scheme竟然比我做得简单得多(尽pipe这是非常糟糕的logging)。 以下代码是我的解决scheme:

 Intent i = (new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com")); PackageManager pm = context.getPackageManager(); final ResolveInfo mInfo = pm.resolveActivity(i, 0); Toast.makeText(context, pm.getApplicationLabel(mInfo.activityInfo.applicationInfo), Toast.LENGTH_LONG).show(); 

下面的launchUrlInDefaultBrowser方法启动一个URL,不显示用户的任何select查询。 首先,它试图find用户的默认浏览器应用程序,并启动它的URL。 其次,如果没有默认的应用程序,它会列出所有能够启动URL的活动,并挑选第一个。 如果活动已启动,则该方法返回true; 否则,是错误的。

 boolean launchUrlInDefaultBrowser(Context context, String url) { final Intent browserIntent = new Intent(Intent.ACTION_VIEW); browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); browserIntent.setData(Uri.parse(url)); // 1: Try to find the default browser and launch the URL with it final ResolveInfo defaultResolution = context.getPackageManager().resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY); if (defaultResolution != null) { final ActivityInfo activity = defaultResolution.activityInfo; if (!activity.name.equals("com.android.internal.app.ResolverActivity")) { browserIntent.setClassName(activity.applicationInfo.packageName, activity.name); context.startActivity(launchIntent); return true; } } // 2: Try to find anything that we can launch the URL with. Pick up the first one that can. final List<ResolveInfo> resolveInfoList = context.getPackageManager().queryIntentActivities(browserIntent, PackageManager.MATCH_DEFAULT_ONLY); if (!resolveInfoList.isEmpty()) { browserIntent.setClassName(resolveInfoList.get(0).activityInfo.packageName, resolveInfoList.get(0).activityInfo.name); context.startActivity(browserIntent); return true; } return false; } 

请注意,OEM可能有自己的ResolverActivity实施。 例如华为有com.huawei.android.internal.app.HwResolverActivity。

在Kitkat AOSP中,getPreferredPackages()总是返回空列表。 源代码如下

 public List<PackageInfo> getPreferredPackages(int flags) { return new ArrayList<PackageInfo>(); }