How to filter specific apps for ACTION_SEND intent (and set a different text for each app)

后端 未结 12 1879
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 01:08

How can you filter out specific apps when using the ACTION_SEND intent? This question has been asked in various ways, but I haven\'t been able to gather a

相关标签:
12条回答
  • 2020-11-22 01:24

    I have improved @dacoinminster answer and this is the result with an example to share your app:

    // Intents with SEND action
    PackageManager packageManager = context.getPackageManager();
    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    sendIntent.setType("text/plain");
    List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(sendIntent, 0);
    
    List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
    Resources resources = context.getResources();
    
    for (int j = 0; j < resolveInfoList.size(); j++) {
        ResolveInfo resolveInfo = resolveInfoList.get(j);
        String packageName = resolveInfo.activityInfo.packageName;
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setComponent(new ComponentName(packageName,
        resolveInfo.activityInfo.name));
        intent.setType("text/plain");
    
        if (packageName.contains("twitter")) {
            intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.twitter) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
        } else {
            // skip android mail and gmail to avoid adding to the list twice
            if (packageName.contains("android.email") || packageName.contains("android.gm")) {
                continue;
            }
            intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForFacebookWhatsapp) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
        }
    
        intentList.add(new LabeledIntent(intent, packageName, resolveInfo.loadLabel(packageManager), resolveInfo.icon));
    }
    
    Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.subjectForMailApps));
    emailIntent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForMailApps) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
    
    context.startActivity(Intent.createChooser(emailIntent, resources.getString(R.string.compartirEn)).putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new LabeledIntent[intentList.size()])));
    
    0 讨论(0)
  • 2020-11-22 01:24

    So simple and concise. Thanks to the Open source developer, cketti for sharing this solution:

    String mailto = "mailto:bob@example.org" +
        "?cc=" + "alice@example.com" +
        "&subject=" + Uri.encode(subject) +
        "&body=" + Uri.encode(bodyText);
    
    Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse(mailto));
    
    try {
      startActivity(emailIntent);
    } catch (ActivityNotFoundException e) {
      //TODO: Handle case where no email app is available
    }
    

    And this is the link to his/her gist.

    0 讨论(0)
  • 2020-11-22 01:27

    This solution shows a list of applications in a ListView dialog that resembles the chooser:

    screenshot

    It is up to you to:

    1. obtain the list of relevant application packages
    2. given a package name, invoke the relevant intent

    The adapter class:

    import java.util.List;
    
    import android.content.Context;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.graphics.drawable.Drawable;
    import android.util.TypedValue;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.TextView;
    
    public class ChooserArrayAdapter extends ArrayAdapter<String> {
        PackageManager mPm;
        int mTextViewResourceId;
        List<String> mPackages;
    
        public ChooserArrayAdapter(Context context, int resource, int textViewResourceId, List<String> packages) {
            super(context, resource, textViewResourceId, packages);
            mPm = context.getPackageManager();
            mTextViewResourceId = textViewResourceId;
            mPackages = packages;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            String pkg = mPackages.get(position);
            View view = super.getView(position, convertView, parent);
    
            try {
                ApplicationInfo ai = mPm.getApplicationInfo(pkg, 0);
    
                CharSequence appName = mPm.getApplicationLabel(ai);
                Drawable appIcon = mPm.getApplicationIcon(pkg);
    
                TextView textView = (TextView) view.findViewById(mTextViewResourceId);
                textView.setText(appName);
                textView.setCompoundDrawablesWithIntrinsicBounds(appIcon, null, null, null);
                textView.setCompoundDrawablePadding((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getContext().getResources().getDisplayMetrics()));
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
    
            return view;
        }
    
    }
    

    and its usage:

        void doXxxButton() {
            final List<String> packages = ...;
            if (packages.size() > 1) {
                ArrayAdapter<String> adapter = new ChooserArrayAdapter(MyActivity.this, android.R.layout.select_dialog_item, android.R.id.text1, packages);
    
                new AlertDialog.Builder(MyActivity.this)
                .setTitle(R.string.app_list_title)
                .setAdapter(adapter, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int item ) {
                        invokeApplication(packages.get(item));
                    }
                })
                .show();
            } else if (packages.size() == 1) {
                invokeApplication(packages.get(0));
            }
        }
    
        void invokeApplication(String packageName) {
            // given a package name, create an intent and fill it with data
            ...
            startActivityForResult(intent, rq);
        }
    
    0 讨论(0)
  • 2020-11-22 01:31

    Thanks to @dacoinminster. I make some modifications to his answer including package names of the popular apps and sorting of those apps.

    List<Intent> targetShareIntents = new ArrayList<Intent>();
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    PackageManager pm = getActivity().getPackageManager();
    List<ResolveInfo> resInfos = pm.queryIntentActivities(shareIntent, 0);
    if (!resInfos.isEmpty()) {
        System.out.println("Have package");
        for (ResolveInfo resInfo : resInfos) {
            String packageName = resInfo.activityInfo.packageName;
            Log.i("Package Name", packageName);
    
            if (packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana")
                    || packageName.contains("com.whatsapp") || packageName.contains("com.google.android.apps.plus")
                    || packageName.contains("com.google.android.talk") || packageName.contains("com.slack")
                    || packageName.contains("com.google.android.gm") || packageName.contains("com.facebook.orca")
                    || packageName.contains("com.yahoo.mobile") || packageName.contains("com.skype.raider")
                    || packageName.contains("com.android.mms")|| packageName.contains("com.linkedin.android")
                    || packageName.contains("com.google.android.apps.messaging")) {
                Intent intent = new Intent();
    
                intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
                intent.putExtra("AppName", resInfo.loadLabel(pm).toString());
                intent.setAction(Intent.ACTION_SEND);
                intent.setType("text/plain");
                intent.putExtra(Intent.EXTRA_TEXT, "https://website.com/");
                intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_text));
                intent.setPackage(packageName);
                targetShareIntents.add(intent);
            }
        }
        if (!targetShareIntents.isEmpty()) {
            Collections.sort(targetShareIntents, new Comparator<Intent>() {
                @Override
                public int compare(Intent o1, Intent o2) {
                    return o1.getStringExtra("AppName").compareTo(o2.getStringExtra("AppName"));
                }
            });
            Intent chooserIntent = Intent.createChooser(targetShareIntents.remove(0), "Select app to share");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
            startActivity(chooserIntent);
        } else {
            Toast.makeText(getActivity(), "No app to share.", Toast.LENGTH_LONG).show();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:32

    I had same problem and this accepted solution didn't helped me, if someone has same problem you can use my code snippet:

    // example of filtering and sharing multiple images with texts
    // remove facebook from sharing intents
    private void shareFilter(){
    
        String share = getShareTexts();
        ArrayList<Uri> uris = getImageUris();
    
        List<Intent> targets = new ArrayList<>();
        Intent template = new Intent(Intent.ACTION_SEND_MULTIPLE);
        template.setType("image/*");
        List<ResolveInfo> candidates = getActivity().getPackageManager().
                queryIntentActivities(template, 0);
    
        // remove facebook which has a broken share intent
        for (ResolveInfo candidate : candidates) {
            String packageName = candidate.activityInfo.packageName;
            if (!packageName.equals("com.facebook.katana")) {
                Intent target = new Intent(Intent.ACTION_SEND_MULTIPLE);
                target.setType("image/*");
                target.putParcelableArrayListExtra(Intent.EXTRA_STREAM,uris);
                target.putExtra(Intent.EXTRA_TEXT, share);
                target.setPackage(packageName);
                targets.add(target);
            }
        }
        Intent chooser = Intent.createChooser(targets.remove(0), "Share Via");
        chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
        startActivity(chooser);
    
    }
    
    0 讨论(0)
  • 2020-11-22 01:34

    You can try the code below, it works perfectly.

    Here we share to some specific apps, that are Facebook, Messenger, Twitter, Google Plus and Gmail.

    public void shareIntentSpecificApps() {
            List<Intent> intentShareList = new ArrayList<Intent>();
            Intent shareIntent = new Intent();
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.setType("text/plain");
            List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(shareIntent, 0);
    
            for (ResolveInfo resInfo : resolveInfoList) {
                String packageName = resInfo.activityInfo.packageName;
                String name = resInfo.activityInfo.name;
                Log.d(TAG, "Package Name : " + packageName);
                Log.d(TAG, "Name : " + name);
    
                if (packageName.contains("com.facebook") ||
                        packageName.contains("com.twitter.android") ||
                        packageName.contains("com.google.android.apps.plus") ||
                        packageName.contains("com.google.android.gm")) {
    
                    if (name.contains("com.twitter.android.DMActivity")) {
                        continue;
                    }
    
                    Intent intent = new Intent();
                    intent.setComponent(new ComponentName(packageName, name));
                    intent.setAction(Intent.ACTION_SEND);
                    intent.setType("text/plain");
                    intent.putExtra(Intent.EXTRA_SUBJECT, "Your Subject");
                    intent.putExtra(Intent.EXTRA_TEXT, "Your Content");
                    intentShareList.add(intent);
                }
            }
    
            if (intentShareList.isEmpty()) {
                Toast.makeText(MainActivity.this, "No apps to share !", Toast.LENGTH_SHORT).show();
            } else {
                Intent chooserIntent = Intent.createChooser(intentShareList.remove(0), "Share via");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentShareList.toArray(new Parcelable[]{}));
                startActivity(chooserIntent);
            }
        }
    
    0 讨论(0)
提交回复
热议问题