Jak filtrować określone aplikacje pod kątem działania ACTION_SEND (i ustawić inny tekst dla każdej aplikacji)

187

Jak możesz odfiltrować określone aplikacje, używając intencji ACTION_SEND? To pytanie zostało zadane na różne sposoby, ale nie byłem w stanie znaleźć rozwiązania na podstawie udzielonych odpowiedzi. Mam nadzieję, że ktoś może pomóc. Chciałbym zapewnić możliwość udostępniania w aplikacji. Zgodnie z radą dewelopera Androida, Alexandra Lucasa , wolałbym to robić, używając intencji, a nie interfejsów API Facebook / Twitter.

Udostępnianie przy użyciu intencji ACTION_SEND

Udostępnianie przy użyciu zamiaru ACTION_SEND jest świetne, ale problem polega na tym, że (1) nie chcę tam wszystkich opcji udostępniania, wolę ograniczyć je do FB, Twittera i poczty e-mail oraz (2) nie chcę udostępniać to samo dotyczy każdej aplikacji do udostępniania . Na przykład w moim twitterowym udziale zamieściłem pewne wzmianki, a hashtagi ograniczyły go do 140 znaków lub mniej, podczas gdy udział na Facebooku będzie zawierać link i obraz funkcji.

Czy można ograniczyć opcje zamiaru ACTION_SEND (udostępnij)? Widziałem coś na temat korzystania z PackageManager i queryIntentActivities, ale nie byłem w stanie zrozumieć połączenia między PackageManager a intencją ACTION_SEND.

LUB

Zamiast filtrować aplikacje do udostępniania, mój problem można również rozwiązać, gdybym mógł użyć zamiaru ACTION_SEND, aby przejść bezpośrednio do Facebooka lub Twittera zamiast otwierać okno dialogowe. Gdyby tak było, mógłbym stworzyć własne okno dialogowe, a kiedy klikną „Facebook”, stworzą intencje specyficzne dla Facebooka i po prostu wyślą je na Facebooka. To samo dotyczy Twittera.

LUB czy to nie jest możliwe? Czy interfejsy API Facebooka i Twittera to jedyny sposób?

Kyle Clegg
źródło
Możliwa duplikat: [niestandardowe filtrowanie-zamiaru-wybierającego-na-zainstalowanym-android-pakiet-nazwa] [1] [1]: stackoverflow.com/questions/5734678/...
Asaf Pinhassi
1
Ten wpis na blogu wydaje się być idealną odpowiedzią: hkdevtips.blogspot.com/2013/02/...
Vitali Olshevski,
2
hej przyjacielu ... kiedy klikam przycisk wysyłania, a następnie otwieram okno dialogowe udostępniania i lista okien dialogowych udostępniania to „Gmail, e-mail, zapiya, podłączenie” itp. ale nie pokazuję Facebooka, WhatsApp, Facebooka, komunikatora, wycieczek ... jak mogę to pokazać?
GB_Bhayani
jak nie pokazywać selektora, gdy jest tylko jeden element / opcja zamierzonego działania na Androidzie 6.0? problem nie pojawia się na mniej niż Androida 6.0
zyskuje

Odpowiedzi:

324

Według mojej wiedzy StackOverflow ma wiele osób zadających to pytanie na różne sposoby, ale nikt jeszcze nie odpowiedział na nie całkowicie.

Moja specyfikacja wezwała użytkownika do wybrania e-maila, Twittera, Facebooka lub SMS-a z niestandardowym tekstem dla każdego z nich. Oto jak to osiągnąłem:

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

W różnych miejscach znalazłem fragmenty tego, jak to zrobić, ale nie widziałem tego wszystkiego w innym miejscu.

Pamiętaj, że ta metoda ukrywa również wszystkie głupie opcje, których nie chcę, na przykład udostępnianie przez Wi-Fi i Bluetooth.

Mam nadzieję, że to komuś pomoże.

Edycja: W komentarzu poproszono mnie o wyjaśnienie, co robi ten kod. Zasadniczo tworzy ACTION_SENDzamiar TYLKO dla natywnego klienta poczty, a następnie przypisuje inne zamiary do selektora. Uczynienie pierwotnego zamiaru specyficznym dla e-maila pozbywa się wszystkich niepotrzebnych śmieci, takich jak Wi-Fi i bluetooth, a następnie biorę inne intencje, których chcę od ACTION_SENDzwykłego zwykłego tekstu, i włączam je, zanim pokażę selektorowi.

Kiedy chwytam dodatkowe zamiary, ustawiam niestandardowy tekst dla każdego z nich.

Edycja2: Minęło trochę czasu, odkąd to opublikowałem, a sprawy się nieco zmieniły. Jeśli widzisz Gmaila dwukrotnie na liście opcji, spróbuj usunąć specjalną obsługę dla „android.gm”, jak sugeruje komentarz w @h_k poniżej.

Ponieważ ta jedna odpowiedź jest źródłem prawie wszystkich moich punktów reputacji przepełnienia stosu, muszę przynajmniej starać się ją aktualizować.

dacoinminster
źródło
1
Używam tego kodu, ale jakoś Evernote wkrada się na listę. Kiedy sprawdzam nazwy pakietów, jest to com.evernote, więc nie jestem pewien, dlaczego tak się dzieje.
James Harpe,
1
@ user2249287 Sugeruję przejście przez kod, aż zobaczysz pomijaną aplikację do przesyłania wiadomości, a następnie spójrz na nazwę pakietu, aby określić ciąg znaków, który należy dodać do białej listy tej aplikacji.
dacoinminster,
1
@Gilbou Hi! Przepraszamy - minęło dużo czasu, odkąd spojrzałem na ten kod. . . O ile pamiętam, polecenie setPackage wybiera jeden cel, do którego dołączysz wszystko inne. Aby uwzględnić lub wykluczyć różne inne zamiary, zalecamy przejrzenie kodu i sprawdzenie nazw pakietów.
dacoinminster
2
Aby filtrować TYLKO aplikacje e-mail, które posiada użytkownik, możesz użyć drugiej odpowiedzi z tego pytania: stackoverflow.com/questions/8701634/send-email-intent . Nie wymaga użycia typu danych message / rfc822, którego używają również inne aplikacje, takie jak EverNote.
mpellegr,
2
@dacoinminster Twój kod jest niesamowity, ponieważ pozwala mi definiować inny tekst dla aplikacji takich jak Twitter i Whatsapp. Aby usunąć zduplikowany Gmail, po prostu wyjąłem „android.gm” z równania. Nadal dostaję Gmaila i wbudowaną aplikację poczty na liście wyboru, a temat i tekst są nadal nienaruszone.
h_k
26

Jeśli chcesz niestandardową opcję, nie powinieneś polegać na domyślnym oknie dialogowym dostarczonym przez Androida dla tej akcji.

Zamiast tego musisz wdrożyć własne. Konieczne będzie zapytanie Menedżera pakietów, w którym pakiety obsługują wymaganą akcję, a następnie na podstawie odpowiedzi zastosujesz filtrowanie i dostosowany tekst.

Konkretnie, przyjrzeć się metodzie queryIntentActivities z PackageManager klasie. Budujesz intencję, która uruchomi domyślne okno dialogowe (intencja ACTION_SEND), przekazujesz ją do tej metody, a otrzymasz listę obiektów zawierających informacje o działaniach, które mogą obsłużyć ten zamiar. Korzystając z tego, możesz wybrać te, które chcesz.

Po zbudowaniu listy pakietów, które chcesz przedstawić, musisz zbudować własne okno dialogowe listy (najlepiej działanie z motywem okna dialogowego), które wyświetli tę listę.

Należy jednak zauważyć, że bardzo trudno jest ustawić niestandardowe okno dialogowe jako domyślne. Problem polega na tym, że motyw użyty w tym oknie dialogowym jest motywem wewnętrznym i nie może być używany przez aplikację. Możesz spróbować uczynić go tak podobnym do natywnego, jak chcesz, lub wybrać całkowicie niestandardowy wygląd (wiele aplikacji robi to podobnie jak aplikacja galerii itp.)

Savvas Dalkitsis
źródło
1
Oznaczenie tej odpowiedzi jako prawidłowej, ponieważ najbardziej odpowiada pierwotne pytanie, mimo że ostatecznie wybrałem inną drogę (patrz moja odpowiedź). Dzięki.
Kyle Clegg,
22

Wypróbuj ten, aby udostępnić tylko trzy aplikacje - Facebook, Twitter, KakaoStory.

public void onShareClick(View v){
    List<Intent> targetShareIntents=new ArrayList<Intent>();
    Intent shareIntent=new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    List<ResolveInfo> resInfos=getPackageManager().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.kakao.story")){
                Intent intent=new Intent();
                intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
                intent.setAction(Intent.ACTION_SEND);
                intent.setType("text/plain");
                intent.putExtra(Intent.EXTRA_TEXT, "Text");
                intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
                intent.setPackage(packageName);
                targetShareIntents.add(intent);
            }
        }
        if(!targetShareIntents.isEmpty()){
            System.out.println("Have Intent");
            Intent chooserIntent=Intent.createChooser(targetShareIntents.remove(0), "Choose app to share");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
            startActivity(chooserIntent);
        }else{
            System.out.println("Do not Have Intent");
            showDialaog(this);
        }
    }
}
użytkownik3098538
źródło
ten kod działa idealnie, jeśli próbujesz podzielić się z konkretnymi aplikacjami
Orcun Sevsay
22

Znalazłem rozwiązanie, które działa dla mnie, patrząc tutaj (patrz trzeci komentarz do pierwszej odpowiedzi). Ten kod wyszukuje prawidłowego klienta Twittera i używa go do opublikowania tweeta. Uwaga: Nie daje Ci zamiaru z różnymi klientami Twittera i pozwala ci wybierać.

Udostępnij za pomocą Twittera:

Intent shareIntent = findTwitterClient(); 
shareIntent.putExtra(Intent.EXTRA_TEXT, "test");
startActivity(Intent.createChooser(shareIntent, "Share"));

Wywołanie tej metody:

public Intent findTwitterClient() {
    final String[] twitterApps = {
            // package // name - nb installs (thousands)
            "com.twitter.android", // official - 10 000
            "com.twidroid", // twidroid - 5 000
            "com.handmark.tweetcaster", // Tweecaster - 5 000
            "com.thedeck.android" }; // TweetDeck - 5 000 };
    Intent tweetIntent = new Intent();
    tweetIntent.setType("text/plain");
    final PackageManager packageManager = getPackageManager();
    List<ResolveInfo> list = packageManager.queryIntentActivities(
            tweetIntent, PackageManager.MATCH_DEFAULT_ONLY);

    for (int i = 0; i < twitterApps.length; i++) {
        for (ResolveInfo resolveInfo : list) {
            String p = resolveInfo.activityInfo.packageName;
            if (p != null && p.startsWith(twitterApps[i])) {
                tweetIntent.setPackage(p);
                return tweetIntent;
            }
        }
    }

    return null;
}

Facebook będzie podobny do „ com.facebook.katana ”, chociaż nadal nie można ustawić tekstu wiadomości (nieaktualne w lipcu 2011 r.).

Źródło kodu: Zamiar otwarcia klienta Twittera na Androida

Kyle Clegg
źródło
4
Nie podoba mi się ta odpowiedź, ponieważ polega ona na znajomości nazw pakietów wszystkich aplikacji Twitter. Aby zobaczyć inny sposób, zobacz stackoverflow.com/questions/6827407/…
Ed Burnette,
Zgadzam się z tobą, chociaż odpowiedź, z którą masz link, ma podobny problem. Nigdy nie lubię polegać na porównaniach łańcuchów, szczególnie gdy nie mam kontroli ani gwarancji, że łańcuch się nie zmieni.
Kyle Clegg,
11

Dzięki @dacoinminster. Wprowadzam pewne zmiany w jego odpowiedzi, w tym nazwy pakietów popularnych aplikacji i sortowanie tych aplikacji.

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();
    }
}
Oguz Ozcan
źródło
9

Możesz wypróbować poniższy kod, działa idealnie.

Tutaj udostępniamy niektóre określone aplikacje, takie jak Facebook, Messenger, Twitter, Google Plus i 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);
        }
    }
Dang Nguyen
źródło
jaki jest powód „if (name.contains („ com.twitter.android.DMActivity ”)) {kontynuuj;}?
isJulian00
8

To rozwiązanie pokazuje listę aplikacji w oknie dialogowym ListView, które przypomina selektor:

zrzut ekranu

Od Ciebie zależy:

  1. uzyskać listę odpowiednich pakietów aplikacji
  2. biorąc pod uwagę nazwę pakietu, wywołaj odpowiednią intencję

Klasa adaptera:

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

}

i jego użycie:

    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);
    }
18446744073709551615
źródło
4

Najczystszym sposobem jest skopiowanie następujących klas: ShareActionProvider, ActivityChooserView, ActivityChooserModel. Dodaj możliwość filtrowania zamiarów w ActivityChooserModel i odpowiednie metody wsparcia w ShareActionProvider. Stworzyłem niezbędne klasy, możesz je skopiować do swojego projektu ( https://gist.github.com/saulpower/10557956 ). Daje to nie tylko możliwość filtrowania aplikacji, którym chcesz się dzielić (jeśli znasz nazwę pakietu), ale także wyłączania historii.

private final String[] INTENT_FILTER = new String[] {
    "com.twitter.android",
    "com.facebook.katana"
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.journal_entry_menu, menu);

    // Set up ShareActionProvider's default share intent
    MenuItem shareItem = menu.findItem(R.id.action_share);

    if (shareItem instanceof SupportMenuItem) {
        mShareActionProvider = new ShareActionProvider(this);
        mShareActionProvider.setShareIntent(ShareUtils.share(mJournalEntry));
        mShareActionProvider.setIntentFilter(Arrays.asList(INTENT_FILTER));
        mShareActionProvider.setShowHistory(false);
        ((SupportMenuItem) shareItem).setSupportActionProvider(mShareActionProvider);
    }

    return super.onCreateOptionsMenu(menu);
}
saulpower
źródło
jak dodać Google + i inne opcje, które zawierają pozostałe aplikacje
Sunishtha Singh
3

Poprawiłem odpowiedź @dacoinminster i oto wynik z przykładem udostępniania aplikacji:

// 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()])));

źródło
3

Miałem ten sam problem i to zaakceptowane rozwiązanie mi nie pomogło, jeśli ktoś ma ten sam problem, możesz użyć mojego fragmentu kodu:

// 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);

}
jemo mgebrishvili
źródło
3
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, 
    Uri.fromParts("mailto", "[email protected]", null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, text);
startActivity(Intent.createChooser(emailIntent, "Send email..."));
Murugan
źródło
0

Tak prosty i zwięzły. Dzięki deweloperowi Open Source, cketti za udostępnienie tego rozwiązania:

String mailto = "mailto:[email protected]" +
    "?cc=" + "[email protected]" +
    "&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
}

I to jest link do jego istoty.

użytkownik10496632
źródło