9

I am trying to get the default/preferred application for a given Intent. For example, when the user installs a second web browser, then attempts to open a URL, he or she will get a dialog like this:

default browser selector

If the user then selects the Use by default for this action option, then the dialog box no longer opens when a URL is pressed.

I am working on an application that should be aware of what this default or preferred app/action is. How do I do this? I am currently using the code below, but getPreferredPackage doesn't return anything:

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();
        }
    }
}

What am I doing wrong? Is this even the right approach?

Phil
  • 35,852
  • 23
  • 123
  • 164
  • I may have found the solution. I am comparing resolveinfo with packageinfo... I will try this first, then delete this question if it works. – Phil Dec 24 '11 at 19:21
  • I did not find the answer, but I did change the code above to reflect my findings (but after testing, it still did not work). – Phil Dec 24 '11 at 19:30

3 Answers3

11

Well, the solution turned out to be much simpler than I made it (although this is very poorly documented). The following code is my solution:

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();
Phil
  • 35,852
  • 23
  • 123
  • 164
  • 4
    what if there is no default app for the given intent ? how would you know about this ? – android developer Dec 17 '12 at 12:28
  • 1
    Google docs say about resolveActivity(): _If multiple matching activities are found and there is no default set, returns a ResolveInfo containing **something else**, such as the activity resolver._ – 18446744073709551615 Dec 09 '13 at 09:26
  • 2
    If there is not default activity for this Intent, here what I got is something like this . ResolveInfo{40df0c50 com.android.internal.app.ResolverActivity p=0 o=0 m=0x0} – androidyue Dec 12 '13 at 05:48
6

The method launchUrlInDefaultBrowser below launches a URL without displaying any selection query for the user. First, it tries to find the user's default browser app and launch the URL with it. Second, if there was no default app, it lists all the capable activities for launching the URL and picks up the first one. In case an activity was launched, the method returns true; otherwise, false.

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;
}

Beware, the OEMs may have their own ResolverActivity implementation. E.g. Huawei has com.huawei.android.internal.app.HwResolverActivity.

Juuso Ohtonen
  • 8,826
  • 9
  • 65
  • 98
0

In Kitkat AOSP, getPreferredPackages() always returns empty list. Source code as below

public List<PackageInfo> getPreferredPackages(int flags) {
    return new ArrayList<PackageInfo>();
}
Kislingk
  • 1,427
  • 14
  • 23