12

I am trying to load a twitter URL in browser.

In my phone, I have already installed twitter app also. I am trying to open URL using ACTION_VIEW intent. But what happens is, when I call intent, android will show default chooser dialog, which contains twitter app also (if it is installed on device). I want to open the URL using browsers only. I want to exclude Twitter application from the dialog. I want all availaible browsers in device to show up in dialog, not native applications like twitter, facebook etc.

Is it is possible or not? If possible could anyone help me in achieving it. I am also attaching my code and a screenshot along with this question for clarity.

String url = "https://twitter.com";
MimeTypeMap map = MimeTypeMap.getSingleton();
String type = map.getMimeTypeFromExtension(url);
Intent i = new Intent(Intent.ACTION_VIEW);
i.setType(type);
i.setData(Uri.parse(url));
startActivity(i);

enter image description here

Sufian
  • 6,405
  • 16
  • 66
  • 120
Sanal Varghese
  • 1,465
  • 4
  • 23
  • 46

3 Answers3

20

I needed to do a similar thing and found this answer helpful. I've modified it so that it is a complete solution:

public static void openFileWithInstalledAppExceptCurrentApp(File file, final Activity activity) {
    Intent intent = new Intent();
    intent.setAction(android.content.Intent.ACTION_VIEW);
    MimeTypeMap mime = MimeTypeMap.getSingleton();
    String ext = file.getName().substring(file.getName().indexOf(".")+1);
    String type = mime.getMimeTypeFromExtension(ext);
    intent.setDataAndType(Uri.fromFile(file),type);
    PackageManager packageManager = activity.getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    String packageNameToHide = "com.test.app";
    ArrayList<Intent> targetIntents = new ArrayList<Intent>();
    for (ResolveInfo currentInfo : activities) {
            String packageName = currentInfo.activityInfo.packageName;
        if (!packageNameToHide.equals(packageName)) {
            Intent targetIntent = new Intent(android.content.Intent.ACTION_VIEW);
            targetIntent.setDataAndType(Uri.fromFile(file),type);
            targetIntent.setPackage(packageName);
            targetIntents.add(targetIntent);
        }
    }
    if(targetIntents.size() > 0) {
        Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), "Open file with");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[] {}));
        activity.startActivity(chooserIntent);
    }
    else {
        Toast.makeText(this, "No app found", Toast.LENGTH_SHORT).show();
    }
}
Community
  • 1
  • 1
Sufian
  • 6,405
  • 16
  • 66
  • 120
  • 2
    You forgot a `!` before `packageNameToHide.equals(packageName)`. Now it allways opens with the packageNameOfAppToHide. – Roel Jan 27 '15 at 10:21
  • @DalvikVM thanks for suggestion. You're both write. I fixed the mistake. :) – Sufian Feb 12 '16 at 07:06
  • @lf215 sorry that your edit was already rejected before I could approve it. I've made the correction. Thanks. :) – Sufian Feb 12 '16 at 07:07
  • 2
    My current app was still listed in the chooser. I had to add this line to fix it: `targetIntent.setComponent(new ComponentName(packageName, currentInfo.activityInfo.name));` – AndyDeveloper Aug 18 '16 at 21:59
  • 1
    why `remove(0)`? –  May 26 '18 at 15:58
  • I believe the `remove(0)` makes the first packagename as the default activity to be used in the chooser dialog ([read this](https://developer.android.com/reference/android/content/Intent#createChooser(android.content.Intent,%20java.lang.CharSequence))). Then in the next line of code I'm setting the others, which doesn't include the defaulted activity since it's been removed from the ArrayList in the line earlier ([read this](https://developer.android.com/reference/android/content/Intent.html#EXTRA_INITIAL_INTENTS)). – Sufian May 26 '18 at 17:54
  • @СергейГрушин please see my comment above. – Sufian May 26 '18 at 18:00
  • @Sufian hm.. it is safely? May be needed check collection size before deleting? –  May 27 '18 at 10:16
  • @СергейГрушин yes in the code I am checking the list size before calling `remove()`. – Sufian May 27 '18 at 11:14
  • Don't forget about case when you've selected default app on device. In this case 'queryIntentActivities' provides only default app. So [use this post](https://stackoverflow.com/a/48209640/2471275) to get list of all apps – Djek-Grif Jan 09 '20 at 13:34
  • also need to add chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); – djdance May 21 '21 at 12:09
4

You just need to set the target package to the intent:

String url = "https://twitter.com";
MimeTypeMap map = MimeTypeMap.getSingleton();
String type = map.getMimeTypeFromExtension(url);
Intent i = new Intent(Intent.ACTION_VIEW);
i.setType(type);
i.setData(Uri.parse(url));
ComponentName comp = new ComponentName("com.android.browser", "com.android.browser.BrowserActivity");
i.setComponent(comp);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

However, users my be disturbed if they have some custom browser installed and want to use this as default.

You can try to detect the default browser with:

Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://example.com"));
List<ResolveInfo> list = context.getPackageManager()
    .queryIntentActivities(i, 0);
// walk through list and select your most favorite browser
flx
  • 14,146
  • 11
  • 55
  • 70
  • no difference, still it shows the same view. I have made a minor change to your code. i don't know whether it is needed or not. This shows almost all apllication in my device. – Sanal Varghese Sep 08 '13 at 11:12
  • here is the modified code. I have commented setting data & type. String url = "https://twitter.com"; MimeTypeMap map = MimeTypeMap.getSingleton(); String type =map.getMimeTypeFromExtension(url); Intent i = new Intent(Intent.ACTION_VIEW); //i.setType(type); //i.setData(Uri.parse(url)); //ComponentName comp = new ComponentName("com.android.browser", "com.android.browser.BrowserActivity"); ComponentName comp = new Intent(type, Uri.parse(url)).resolveActivity(this. getPackageManager()); i.setComponent(comp); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); – Sanal Varghese Sep 08 '13 at 11:13
  • you are asking the system for a list of apps who can handle "http://twitter.com" which includes the twitter app.. that's why i chose http://google.com for the test. – flx Sep 08 '13 at 11:17
  • That i knew. When you gave google.com, it will not show twitter. But what i want is when I use a twitter url, i want it to open in browser rather than twitter app. – Sanal Varghese Sep 08 '13 at 15:02
  • Again: That's why I ask for the ComponentName handling http://google.com, in your case this is the IntentChooser. Use my first advise, and it will open the browser. – flx Sep 09 '13 at 01:53
  • I just changed the second part. hopfully, it's more clear now. – flx Sep 09 '13 at 02:00
0

Take a look at Intent.EXTRA_EXCLUDE_COMPONENTS. It's exactly what you need, but available only at API 24+.

In my case I had a link to open in browser. Here as an Intent for it:

    val intent = Uri
        .parse(url)
        .let { Intent(Intent.ACTION_VIEW, it) }
        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

Then I searched for packages that I want to exclude, e.g. "twitter"

    val excludedApps = packageManager.queryIntentActivities(intent, 0)
        .filter { it.activityInfo.name.contains("twitter") }
        .map {
            ComponentName(it.activityInfo.packageName, it.activityInfo.name)
        }

And then started a chooser with filtered apps

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        Intent
            .createChooser(intent, null)
            .putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedApps.toTypedArray())
    } else {
        // API 23 and older ignored here
        intent
    }.let {
        startActivity(it)
    }
Flovettee
  • 895
  • 1
  • 8
  • 9