среда, 4 января 2012 г.

Отправка email средствами системы

Большинство примеров рассказывают, что программно отправить почтовое сообщение в Android - дело не хитрое. Создавай Intent с действием ACTION_SEND, добавляй туда адрес получателя, заголовок и сообщение, после чего вызывай метод startActivity() и дело в шляпе.
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"test@test.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Message body");
emailIntent.setType("text/plain");
startActivity(emailIntent);
Традиционно, все несколько сложнее. Данный код приведет к запуску программы по умолчанию для действия ACTION_SEND с типом text/plain и это не обязательно будет почтовый клиент. И только если программа по умолчанию не выбрана, то откроется диалог выбора нужной программы. Чтобы диалог открывался всегда нужно послать другой Intent, который будет включать в себя ранее подготовленный Intent для отправки почтового сообщения. Такой Intent создает статический метод Intent.createChooser().
Но это еще не все. В открывающемся списке, кроме почтовых программ будет фигурировать еще множество сторонних приложений и Bluetooth. Этого можно попробовать избежать, если изменить тип данных с text/plain на application/octet-stream. Тогда, в большинстве случаев, выбор будет идти только среди установленных на устройстве почтовых клиентов. Bluetooth остается в списке на устройстве Samsung Galaxy с версией Android 2.2, но зависит ли это от модели или от версии операционной системы я найти информации не смог.
Гарантировано отправить письмо в формате html можно только через GMail, все остальные клиенты, которые я просмотрел, игнорируют html теги. Для html письма не обязательно задавать тип text/html, но нужно конвертировать обычный String в Spanned с помощью метода Html.fromHtml(). В итоге финальный код выглядит таким образом:
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"test@test.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT,
 Html.fromHtml("<b>Bold message body</b>"));
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:/sdcard/test.txt"));
emailIntent.setType("application/octet-stream");
startActivity(Intent.createChooser(emailIntent, "Send Email"));
На рисунке ниже изображен вид системного диалога выбора программы в зависимости от указанного типа данных. Диалоги будут отличаться на разных устройствах, в зависимости от установленных на них приложениях, но общая концепция такая: чем более общий тип данных будет указан тем больше приложений будет готово их переслать.

Можно вложить в письмо файл с SD карты. Для этого надо путь к файлу преоброзовать в URI и добавить в intent под именем Intent.EXTRA_STREAM
//...
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:/sdcard/test.txt"));
//...
Чтобы вложить несколько файлов надо сделать чуть больше действий:
  • поменять действие в intent на Intent.ACTION_SEND_MULTIPLE
  • создать ArrayList со списком файлов
  • добавить в intent массив с помощью putParcelableArrayListExtra
ArrayList<uri> uris = new ArrayList<uri>();
uris.add(Uri.parse("file:/sdcard/test_01.txt"));
uris.add(Uri.parse("file:/sdcard/test_02.txt"));
  
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { "test@test.com" });
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT,
 Html.fromHtml("<b>Bold message body</b>"));
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
emailIntent.setType("application/octet-stream");
startActivity(emailIntent);
При необходимости можно отправить письмо через конкретный почтовый клиент. Для этого необходимо знать название его пакета, класса нужной Activity и обработать исключения при вызове метода startActivity() так как существует вероятность, что необходимой программы на устройстве пользователя не окажется. Для клиента GMail пакет называется com.google.android.gm, а нужный класс com.google.android.gm.ComposeActivityGmail.
Модифицированный код выглядит так:
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { "test@test.com" });
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT,
 Html.fromHtml("<b>Bold message body</b>"));
emailIntent.setType("application/octet-stream");
emailIntent.setClassName("com.google.android.gm",
 "com.google.android.gm.ComposeActivityGmail");
try {
 startActivity(emailIntent);
} catch (android.content.ActivityNotFoundException ex) {
 // GMail not found
}

Комментариев нет:

Отправить комментарий