Як відкрити програму електронної пошти через Intents (але лише програму електронної пошти)


76

Я хочу налаштувати частину моєї програми, яка дозволяє користувачам надсилати швидкий електронний лист іншому користувачеві. Це не дуже складно налаштувати:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, message);
Intent mailer = Intent.createChooser(intent, null);
startActivity(mailer);

Однак проблема полягає в тому, що ACTION_SEND приймається не лише програмами електронної пошти - наприклад, на моєму телефоні додаток Facebook, Twitter, reddit - це весело, і навіть Bluetooth є життєздатною альтернативою надсилання цього повідомлення. Повідомлення є занадто довгим для деяких із них (особливо Twitter).

Чи є спосіб обмежити вибір лише програмами, які підтримують довгі повідомлення (наприклад, електронну пошту)? Або є спосіб виявити додаток, який обрав користувач, і відповідно налаштувати повідомлення?


2
Мені цікаво, як клас Linkify вирішує, що відкрити для посилань на пошту. Можливо, перевірте вихідний код Linkify і опублікуйте свої висновки.
Pentium10,

Гарний дзвінок - я перевірю це та повідомлю вас, якщо знайду щось цікаве.
Dan Lew

Ще раз спасибі Pentium10, гарна порада щодо пошуку, як Linkify робить щось.
Dan Lew

Відповіді:


84

Зміна типу MIME - це відповідь, це те, що я зробив у своєму додатку, щоб змінити таку ж поведінку. я використавintent.setType("message/rfc822");


2
Я не вважаю, що кожна програма електронної пошти підтримує цей тип MIME.
CommonsWare

2
У моєму пристрої вказано Gmail, а також "Drive" та "AndFTP"
Amir Uval

9
Я використовую новий намір (Intent.ACTION_SENDTO, Uri.parse ("mailto:"));
Ерік Кохран

93

Завдяки пропозиції Pentium10 шукати, як працює Linkify, я знайшов чудове рішення цієї проблеми. В основному, ви просто створюєте посилання "mailto:", а потім викликаєте відповідний намір для цього .:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.parse("mailto:?subject=" + subject + "&body=" + body);
intent.setData(data);
startActivity(intent);

У цього рішення є кілька цікавих аспектів:

  1. Я використовую дію ACTION_VIEW, оскільки це більше підходить для посилання "mailto:". Ви не можете надати жодних конкретних дій, але тоді ви можете отримати незадовільні результати (наприклад, він запитає вас, чи хочете ви додати посилання до своїх контактів).

  2. Оскільки це посилання "поділитися", я просто не включаю жодної адреси електронної пошти - хоча це посилання на пошту. Це працює.

  3. Тут немає жодного вибору. Причиною цього є надання користувачеві можливості скористатися типовими параметрами; якщо вони встановили програму електронної пошти за замовчуванням, то вони переведуть їх прямо до цього, в обхід селектора (що, на мій погляд, здається хорошим, ви можете заперечити інакше).

Звичайно, є багато тонкощів, які я залишаю позаду (наприклад, правильне кодування предмета / тіла), але ви повинні мати можливість це зрозуміти самостійно.


З усього розв’язання проблеми це спрацювало для мене Дякую, приятелю :)
Бора

2
це найкращий метод imo, оскільки він не відображає Snapchat, Telegram та інші програми, які дозволяють надсилати текст
WuerfelDev

5
У випадках, якщо комусь потрібно, ви вказуєте приймач із "& to"
SpiralDev

29

Це спрацювало для мене

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.setType("vnd.android.cursor.item/email");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {"abc@xyz.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Email Subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "My email content");
startActivity(Intent.createChooser(emailIntent, "Send mail using..."));

1
Працював як шарм. Особливо зверніть увагу, що Extra_Email має бути в масиві String, або To: буде порожнім ...
Nilesh

4

Ви пробували включати Intent.EXTRA_EMAILзайве?

Intent mailer = new Intent(Intent.ACTION_SEND);
mailer.setType("text/plain");
mailer.putExtra(Intent.EXTRA_EMAIL, new String[]{"name@email.com"});
mailer.putExtra(Intent.EXTRA_SUBJECT, subject);
mailer.putExtra(Intent.EXTRA_TEXT, bodyText);
startActivity(Intent.createChooser(mailer, "Send email..."));

Це може обмежити список доступних програм приймачів ...


2
Я спробував це, не допомагає. Додаткові функції не використовуються для фільтрування програм у програмі вибору.
Dan Lew

Я думаю, єдиним іншим рішенням було б запустити певну поштову програму, передавши рядок із повним шляхом до класу / пакету. Це обмежить ваших користувачів одним поштовим додатком, але перешкоджатиме застосуванню інших типів програм (наприклад, Twitter) ...
обожнювати

1
Мені ця ідея зовсім не подобається, тому що для початку у більшості користувачів буде дві програми пошти за замовчуванням (стандартна програма Mail та Gmail), і я не хочу гадати, яку саме вони використовують.
Dan Lew

У мене 4 поштові клієнти і я майже не користуюся програмами Gmail та Mail.
Pentium10,

1

Спробуйте це

Intent intent = new Intent("android.intent.action.SENDTO", Uri.fromParts("mailto", "yourmail@gmail.com", null));
intent.putExtra("android.intent.extra.SUBJECT", "Enter Subject Here");
startActivity(Intent.createChooser(intent, "Select an email client")); 

1

Жодне з рішень не працювало для мене. Спасибі розробнику з відкритим кодом, cketti за те, що він поділився своїм стислим та акуратним рішенням.

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
}

І це посилання на його / її суть.


Це буквально єдине, що працює, і я спробував 6 різних рішень. Дякую.
Code Wiget

0

Спробуйте змінити тип MIME із звичайного на повідомлення

intent.setType("text/message");

0

Це трохи друкарська помилка, оскільки вам потрібно змінити свій mimeype:

intent.setType("plain/text"); //Instead of "text/plain"

1
Наскільки мені відомо, plain/textце не дійсний тип MIME. У вас є посилання на це?
Томас


-1

НАДІСЛАТИ ТІЛЬКИ КЛІЄНТАМ НА ЕЛЕКТРОННУ ПОШТУ - ЗА БЕЗКОШТОВНИМИ НАДАННЯМИ

Рішень багато, але всі працюють частково.

mailto правильно фільтрує програми електронної пошти, але він не може не надсилати потоки / файли.

повідомлення / rfc822 відкриває пекло програм разом із поштовими клієнтами

отже, рішенням цього є використання обох.

  1. Спочатку розв’яжіть наміри, використовуючи mailto intent
  2. Потім встановіть дані для кожного виду діяльності, вирішеного для надсилання необхідних даних
private void share()
{
     Intent queryIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
     Intent dataIntent  = getDataIntent();

     Intent targetIntent = getSelectiveIntentChooser(context, queryIntent, dataIntent);
     startActivityForResult(targetIntent);
}

Створіть необхідний намір даних, який заповнений необхідними даними для спільного використання

private Intent getDataIntent()
{
        Intent dataIntent = buildIntent(Intent.ACTION_SEND, null, "message/rfc822", null);

        // Set subject
        dataIntent.putExtra(Intent.EXTRA_SUBJECT, title);

        //Set receipient list.
        dataIntent.putExtra(Intent.EXTRA_EMAIL, toRecipients);
        dataIntent.putExtra(Intent.EXTRA_CC, ccRecipients);
        dataIntent.putExtra(Intent.EXTRA_BCC, bccRecipients);
        if (hasAttachments())
        {
            ArrayList<Uri> uris = getAttachmentUriList();

            if (uris.size() > 1)
            {
                intent.setAction(Intent.ACTION_SEND_MULTIPLE);
                dataIntent.putExtra(Intent.EXTRA_STREAM, uris);
            }
            else
            {
                dataIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris.get(0));
            }
        }

        return dataIntent;
}

protected ArrayList<Uri> getAttachmentUriList()
{
        ArrayList<Uri> uris = new ArrayList();
        for (AttachmentInfo eachAttachment : attachments)
        {
            uris.add(eachAttachment.uri);
        }

        return uris;
}

Клас Utitlity для фільтрації необхідних намірів на основі наміру запиту

// Placed in IntentUtil.java
public static Intent getSelectiveIntentChooser(Context context, Intent queryIntent, Intent dataIntent)
{
        List<ResolveInfo> appList = context.getPackageManager().queryIntentActivities(queryIntent, PackageManager.MATCH_DEFAULT_ONLY);

        Intent finalIntent = null;

        if (!appList.isEmpty())
        {
            List<android.content.Intent> targetedIntents = new ArrayList<android.content.Intent>();

            for (ResolveInfo resolveInfo : appList)
            {
                String packageName = resolveInfo.activityInfo != null ? resolveInfo.activityInfo.packageName : null;

                Intent allowedIntent = new Intent(dataIntent);
                allowedIntent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
                allowedIntent.setPackage(packageName);

                targetedIntents.add(allowedIntent);
            }

            if (!targetedIntents.isEmpty())
            {
                //Share Intent
                Intent startIntent = targetedIntents.remove(0);

                Intent chooserIntent = android.content.Intent.createChooser(startIntent, "");
                chooserIntent.putExtra(android.content.Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[]{}));
                chooserIntent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION);

                finalIntent = chooserIntent;
            }

        }

        if (finalIntent == null) //As a fallback, we are using the sent data intent
        {
            finalIntent = dataIntent;
        }

        return finalIntent;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.