At first you're going to think "Wait, this question is a duplicate!". Read on.
I'm trying to use the Intent ACTION_SENDTO
(with an Email URI as data) in order to have just email apps respond.
(Using ACTION_SEND
launches a standard "SEND" chooser with no data URI meaning that non email apps, such as Google Drive, also respond).
My problem is that the attachment works with ACTION_SEND
on all devices, however - when using ACTION_SENDTO
only some devices correctly attach the files. Nexus 7 works but Samsung Galaxy Tab and Acer Iconia don't.
You can see below the different methods side by side:
String email = getActivity().getResources().getString(R.string.supportEmail);
String subject = getActivity().getResources().getString(R.string.sFeedback);
subject = String.format(subject,
getActivity().getResources().getString(R.string.productName));
String content = getActivity().getResources().getString(R.string.whatFeedbackWouldYouLikeToProvide) + "\n\n" +
mMessage.getText().toString();
File toSend = new File(outfile);
if(toSend.exists()) {
Log.e("Feedback", "File path: " + toSend.getAbsolutePath());
Intent emailIntent = new Intent(android.content.Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse("mailto:" +email));
emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, Uri.fromFile(toSend));
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, content);
/* Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("message/rfc822");
emailIntent.putExtra(Intent.EXTRA_EMAIL , new String[]{email});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT , content);
emailIntent.putExtra(Intent.EXTRA_STREAM , Uri.fromFile(toSend)); */
try {
startActivity(emailIntent);
} catch (ActivityNotFoundException anfe) {
Toast.makeText(getActivity(), getResources().getString(R.string.pleaseInstallAnEmailClientInOrderToSendUsFeedback), 8000).show();
}
}
You can see that the filepaths don't seem to be the problem, I've added in some logging which reports:
Samsung Gives:
04-11 11:40:09.953: E/Feedback(6286): File path: /storage/sdcard0/logs.zip
Nexus Gives:
04-11 11:38:59.249: E/Feedback(12702): File path: /storage/emulated/0/logs.zip
(Both based on getExternalStorageDirectory()
to ensure cross application access).
Does anybody know why the difference?
Try to resolve activity via ACTION_SENDTO, but actually sending via ACTION_SEND.
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto", "", null));
intent.putExtra(Intent.EXTRA_SUBJECT, title);
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.putExtra(Intent.EXTRA_STREAM, getSnapshotUri(snapshot, context, event));
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, 0);
if (resolveInfos.size() == 0) {
new AlertDialog.Builder(context)
.setMessage(R.string.no_mail_app)
.setPositiveButton(R.string.ok, null)
.show();
} else {
String packageName = resolveInfos.get(0).activityInfo.packageName;
String name = resolveInfos.get(0).activityInfo.name;
intent.setAction(Intent.ACTION_SEND);
intent.setComponent(new ComponentName(packageName, name));
context.startActivity(intent);
}
The only solution I came up with is the following one. It is a mix of some others I have found while searching for a complete answer. The following will show only email apps and allow including attachments. The most important part was found here: https://stackoverflow.com/a/8550043/4927659
ArrayList<Uri> uris = new ArrayList<>();
uris.add(Uri.parse("file://" + filepath));
//filepath is something like that: /mnt/sdcard/DCIM/DSC0001.JPG
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto", "example@gmail.com", null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Mail subject");
List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities(emailIntent, 0);
List<LabeledIntent> intents = new ArrayList<>();
for (ResolveInfo info : resolveInfos) {
Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"example@gmail.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Mail subject");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); //ArrayList<Uri> of attachment Uri's
intents.add(new LabeledIntent(intent, info.activityInfo.packageName, info.loadLabel(getPackageManager()), info.icon));
}
Intent chooser = Intent.createChooser(intents.remove(intents.size() - 1), "Send email with attachments...");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new LabeledIntent[intents.size()]));
startActivity(chooser);
I encountered the similiar problem and was scratching my head all day, until I found a potential answer on a Chinese blog: http://flysnow.iteye.com/blog/1128354
Nearly to the end of the article, it talks about the intent filters that Android's built-in email client has:
<activity
android:name=".activity.MessageCompose"
android:label="@string/app_name"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.SEND" />
<data android:mimeType="text/plain" />
<data android:mimeType="image/*" />
<data android:mimeType="video/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
You can see it has two intent filters to handle SEND and SENDTO intents differently, and only SEND is specified with mimeType. The code snippet was way back to Android 1.6 but it hasn't been changed much. You can find it in the recent version:
https://android.googlesource.com/platform/packages/apps/Email/+/f44b729bff619d0a9f0b1492726351e41c1e5d5d/AndroidManifest.xml
I'm not sure why they don't specify mimeType in SENDTO intent, but that's the way it is, I think most email client probably doing the same way (except for Gmail, it can successfully attach file when using SENDTO intent). Could that also be your case? Therefore, to be safe you should only send attachment using the SEND intent.
you could try putting the subject and body in the Uri. This question seems to imply that might resolve the problem.
The thing is Intent.ACTION_SEND
is handled by different email clients correctly even if recepient is specified (that is incorrect, but..). So one must use this action if wants to support other clients than Gmail. That is just how it works.
And to add recepient just add exactly the same line you'd add if were using Intent.ACTION_SENDTO
:
Intent emailIntent = new Intent(Intent.ACTION_SEND);
String mailto = "abc@def.com";
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{mailTo});
...
In my case file attachment was not added in clients other than Gmail with Intent.ACTION_SENDTO
and switching to Intent.ACTION_SEND
solved it.