3

I try to filter specific apps when using the ACTION_SEND following the instruction from How to filter specific apps for ACTION_SEND intent (and set a different text for each app)

It worked perfectly on my phone(Android M4 Aqua) , but when I used a LG G3 phone , it duplicated the gmail and didn't filter the Android Beam , Zalo, Blue Mail ... .

It showed like the picture below: Filter List

Here is the code from the link above :

public void onShareClick(View v) {
Resources resources = getResources();

Intent emailIntent = new Intent();
emailIntent.setAction(Intent.ACTION_SEND);
// Native email client doesn't currently support HTML, but it doesn't hurt to try in case they fix it
emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_native)));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
emailIntent.setType("message/rfc822");

PackageManager pm = getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_SEND);     
sendIntent.setType("text/plain");


Intent openInChooser = Intent.createChooser(emailIntent, resources.getString(R.string.share_chooser_text));

List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();        
for (int i = 0; i < resInfo.size(); i++) {
    // Extract the label, append it, and repackage it in a LabeledIntent
    ResolveInfo ri = resInfo.get(i);
    String packageName = ri.activityInfo.packageName;
    if(packageName.contains("android.email")) {
        emailIntent.setPackage(packageName);
    } else if(packageName.contains("twitter") || packageName.contains("facebook") || packageName.contains("mms") || packageName.contains("android.gm")) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(packageName, ri.activityInfo.name));
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("text/plain");
        if(packageName.contains("twitter")) {
            intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_twitter));
        } else if(packageName.contains("facebook")) {
            // Warning: Facebook IGNORES our text. They say "These fields are intended for users to express themselves. Pre-filling these fields erodes the authenticity of the user voice."
            // One workaround is to use the Facebook SDK to post, but that doesn't allow the user to choose how they want to share. We can also make a custom landing page, and the link
            // will show the <meta content ="..."> text from that page with our link in Facebook.
            intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_facebook));
        } else if(packageName.contains("mms")) {
            intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_sms));
        } else if(packageName.contains("android.gm")) { // If Gmail shows up twice, try removing this else-if clause and the reference to "android.gm" above
            intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_gmail)));
            intent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));               
            intent.setType("message/rfc822");
        }

        intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon));
    }
}

// convert intentList to array
LabeledIntent[] extraIntents = intentList.toArray( new LabeledIntent[ intentList.size() ]);

openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
startActivity(openInChooser);       
 }

And here is my debug on LG G3 phone : debug on LG G3

-The "intentList" is the same intentList in the code above (the List "intentList")

-The "resolveInfoList" is the List "resInfo"

-the "list" is just a test list which I use to add the sending package name As you can see , the "intentList " only contains one item (the gmail package item) but the filter list on G3 show 6 items : Two Gmail, Zalo, Android Beam, Email , BlueMail. I could not figure out why it was different from the intent list .Can someone show me what is wrong in the code (which worked perfectly on my Android M4 Aqua ) UPDATED I updated my code following the comment of keivan Esbati and i nearly catched what i want but there was a problem , if i added gmail like this :

    public void onShareClick() {
    Resources resources = getResources();

    Intent emailIntent = new Intent();
    emailIntent.setAction(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:"));
    emailIntent.putExtra(Intent.EXTRA_TEXT, "123");
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "q23");

    PackageManager pm = getPackageManager();
    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    sendIntent.setType("text/plain");


    Intent openInChooser = Intent.createChooser(emailIntent, "string");

    List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
    List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
    for (int i = 0; i < resInfo.size(); i++) {
        ResolveInfo ri = resInfo.get(i);
        String packageName = ri.activityInfo.packageName;
        if (packageName.contains("android.email")) {
            emailIntent.setPackage(packageName);
        }

        if (packageName.contains("android.gm")) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName(packageName,
                ri.activityInfo.name));
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_TEXT, shareText.getText()
                .toString());
            intent.putExtra(Intent.EXTRA_SUBJECT,
                getString(R.string.intent_subject));
            intentList.add(new LabeledIntent(intent, packageName, ri
                .loadLabel(pm), ri.icon));
        }
    }

, it would have worked in LG G3 but in Sony M4 it only showed default mail .Whereas , if i deleted it like the code below :

    public void onShareClick() {
        Resources resources = getResources();

        Intent emailIntent = new Intent();
        emailIntent.setAction(Intent.ACTION_SENDTO);
        emailIntent.setData(Uri.parse("mailto:"));

        emailIntent.putExtra(Intent.EXTRA_TEXT, "123");
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "q23");

        PackageManager pm = getPackageManager();
        Intent sendIntent = new Intent(Intent.ACTION_SEND);
        sendIntent.setType("text/plain");


        Intent openInChooser = Intent.createChooser(emailIntent, "string");

        List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
        List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
        for (int i = 0; i < resInfo.size(); i++) {
            ResolveInfo ri = resInfo.get(i);
            String packageName = ri.activityInfo.packageName;
            if (packageName.contains("android.email")) {
                emailIntent.setPackage(packageName);
            }
        }
   //tried to remove duplicated items but it didn't work
  Set<LabeledIntent> stringSet=new HashSet<LabeledIntent>();
        stringSet.addAll(intentList);
        intentList.clear();
        intentList.addAll(stringSet);
        LabeledIntent[] extraIntents = intentList.toArray(new LabeledIntent[intentList.size()]);
        openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
        startActivity(openInChooser);
    }

even i tried to remove the duplicate item in the labeled list using hashmap , it didn't work , still two gmail items remained in the list .How do i get rid of it ?

Community
  • 1
  • 1
Btnisme123
  • 87
  • 7

1 Answers1

1

It is because of Intent.EXTRA_INITIAL_INTENTS flag; This flag tell chooser to add Apps that support specific intent along the initial Intent's Apps. Since Gmail app supports both emailIntent and sendIntent it appears twice in the list. You can simply remove android.gm part since Gmail support message/rfc822 messages anyway..

Update: Since you create chooser for two Intent you have to query both intent and only add Apps that aren't duplicate, so Query Email Intent first, add all apps, then query Send Intent but Only add Applications that their Package names aren't already present.

Keivan Esbati
  • 3,376
  • 1
  • 22
  • 36
  • I changed the flag from Intent.EXTRA_INITIAL_INTENTS to EXTRA_SHORTCUT_NAME(or ACTION_SEND) and the dupication disappeared but the Android Beam still remained. Can you suggest me what kind of intent i should choose and why ? – Btnisme123 Mar 07 '17 at 06:51
  • If I'm not wrong that Icon belong to GoodNFC App, this means that app is fully qualified to accept your intent.. you can Filter message/rfc822 too but I do not advice you to do so since it gonna limit user selection. – Keivan Esbati Mar 07 '17 at 06:58
  • But you can change your email intent to this so NFC apps wont respond to it (Only email apps will respond): Intent intent = new Intent(Intent.ACTION_SENDTO); intent.setData(Uri.parse("mailto:")); – Keivan Esbati Mar 07 '17 at 07:00
  • I changed "emailIntent" Action from SEND to SENDTO and added intent.setData(Uri.parse("mailto:")) like you said but it only showed a dialog with a text : "No application can perform this action ". – Btnisme123 Mar 07 '17 at 07:17
  • Sry, forgot to mention that you should remove emailIntent.setType("message/rfc822") part.. For complete sample you can check Google official guide: https://developer.android.com/guide/components/intents-common.html#Email – Keivan Esbati Mar 07 '17 at 07:24
  • Also please don't forget to mark answer, since the question was originally about duplication. – Keivan Esbati Mar 07 '17 at 07:28
  • I nearly catched the answer but there was a problem , if i removed the "package gmail" condition , it worked in LG G3 , but there was only default mail in Sony M4 . Whereas , if i remained that block code , it worked perfectly in Sony M4 but duplicated gmail in LG G3(even when I tried to remove duplicate items using hashmap). You can the detail i updated in the question. – Btnisme123 Mar 07 '17 at 08:05
  • I Updated my answer, the code part should be easy to implement, it seems you just forgot that if you don't query the first Intent you cant find Duplicates to remove. Since you create chooser for two Intent it's inevitable that you cross duplicate apps, so one way is to remove same packages manually. – Keivan Esbati Mar 07 '17 at 08:34
  • Sorry but i am still feeling confused , i only add apps after i run the for loop and check if the package meet the condition or not , how do i add them first and then add which is not present ? can you give me an example ? – Btnisme123 Mar 07 '17 at 09:06
  • @Btnisme123 you already query and add compatible apps (queryIntentActivities) but you forgot to query your first intent too.. (you added first intent to chooser and Queried the Second intent only). Just Query your first intent like second one and add it to list only if it isn't already available.. – Keivan Esbati Mar 08 '17 at 07:12