Sharing text from app to Email app in android - android

I have the following code which used to send text from my app to Email:
Intent mail = new Intent(Intent.ACTION_VIEW);
mail.setClassName("com.google.android.gm","com.google.android.gm.ComposeActivityGmail");
mail.putExtra(Intent.EXTRA_EMAIL, new String[] { });
mail.setData(Uri.parse(""));
mail.putExtra(Intent.EXTRA_SUBJECT, "Country Decryption");
mail.setType("plain/text");
mail.putExtra(Intent.EXTRA_TEXT, "my text");
ctx.startActivity(mail);
It works , but as you see, it uses Gmail app, how do I make it use Email application instead of Gmail?
I mean this app:
and what about sharing to Facebook ? I found that Facebook does not support sharing using intent anymore, and I have to use Facebook SDK, but I couldn't find any simple procedure to do that. Is there any simple way?
Regards.

well to use other email apps am afraid you would have to create a chooser dialog and let the user choose which app to use, something like this
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto","abc#mail.com", null));
emailIntent.putExtra(Intent.EXTRA_EMAIL, "address");
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Body");
startActivity(Intent.createChooser(emailIntent, "Send Email..."));

You have to create a specific filter on your ACTION_SEND and you can read a complete answer here.
This is the code in which you can choose which app show in the app chooser
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));
}
}

This works to intent just the gmail app.
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.setPackage("com.google.android.gm");
String shareBody = "Here is the share content body";
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Subject Here");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
startActivity(sharingIntent);

Related

How to export and import SQLite Database from Android Studio? [duplicate]

I created my own file extension (.oli). If the user clicks on a file with this extension my app starts and loads the included data. This works like expected. The problem is I would like to give the user of my app the opportunity to share a file (Example: filename.oli).
I implemented this so far:
public void shareFile(){
File file = getShareableFile(); //Creates a .oli-file
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri uri = Uri.fromFile(file);
shareIntent.setType("*/*"); //Maybe the problem
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, name);
startActivity(Intent.createChooser(shareIntent, getString(R.string.shareDatei)));
}
The problem is, the list of apps that think they could handle sharing my file is very large because of shareIntent.setType("/"); Here are two cases that happen if you share with different apps:
If I choose an Email-app like Gmail to share my file it works how it should. The email includes the file as filename.oli . When I click on it my app gets started.
But If I choose for example the Quickmemo-app I get a message that this file can not be shared by this.
So all in all I just want to show apps in the chooserlist that can handle to share my file with the .oli extension . How do I do that? Thanks in advance!
The setType() intent method actually uses MIME types to filter apps according to the docs. So, you'll only be able to filter the apps available based on the following filters:
1.Text
sendIntent.setType("text/plain");
2. Binary
shareIntent.setType("image/jpeg");
3. Multiple content items
shareIntent.setType("image/*");
EDIT
Here's what I would likely do, I would know which apps I want to be able to share the file, like gmail since you know that works, and I would be selective about which apps are in the list. The following code comes from the answer in this SO link: How to filter specific apps for ACTION_SEND intent (and set a different text for each app)
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);
}

How to send Email with attachment using only email apps?

There are two requirements:
Email with attachment
In the Intent chooser, there should be only Email apps.
What I have known/done:
Intent.ACTION_SENDTO with intent.setData(Uri.parse("mailto:")) can make sure that there are only Email apps in Intent chooser but it will not bring attachment(For some apps like Gmail it will, but there are also many apps that will ignore attachment).
Intent.ACTION_SEND can send Email with attachment. However, in Intent chooser, there will be apps that are actually not Email apps but can response to Intent.ACTION_SEND. Using intent.setType("message/rfc822") can reduce number of those apps but not all.
References this answer: https://stackoverflow.com/a/8550043/3952691 and nearly succeed in my goals. My code is as below:
private static void sendFeedbackWithAttachment(Context context, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0);
if (resolveInfos.isEmpty()) {
Toast.makeText(context, context.getString(R.string.error_activity_not_found),
Toast.LENGTH_SHORT).show();
} else {
// ACTION_SEND may be replied by some apps that are not email apps. However,
// ACTION_SENDTO doesn't allow us to choose attachment. As a result, we use
// an ACTION_SENDTO intent with email data to filter email apps and then send
// email with attachment by ACTION_SEND.
List<LabeledIntent> intents = new ArrayList<>();
Uri uri = getLatestLogUri();
for (ResolveInfo info : resolveInfos) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setPackage(info.activityInfo.packageName);
i.setClassName(info.activityInfo.packageName, info.activityInfo.name);
i.putExtra(Intent.EXTRA_EMAIL, new String[] { Def.Meta.FEEDBACK_EMAIL });
i.putExtra(Intent.EXTRA_SUBJECT, subject);
i.putExtra(Intent.EXTRA_STREAM, uri);
intents.add(new LabeledIntent(i, info.activityInfo.packageName,
info.loadLabel(context.getPackageManager()), info.icon));
}
Intent chooser = Intent.createChooser(intents.remove(0),
context.getString(R.string.send_feedback_to_developer));
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,
intents.toArray(new LabeledIntent[intents.size()]));
context.startActivity(chooser);
}
}
However, on some devices(For example, Xiaomi 2S with MIUI V5, I don't know if this can be influenced by a third-party rom), the result is an empty Intent chooser. And it seems that above Android 6.0, Intent.EXTRA_INITIAL_INTENTS has some bugs(Custom intent-chooser - why on Android 6 does it show empty cells?, and another one: https://code.google.com/p/android/issues/detail?id=202693).
As a result, I don't know how to achieve my goals. Please help me, thank you in advance.
Try the below code to Send a mail
String filename="filename.vcf";
File filelocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), filename);
Uri path = Uri.fromFile(filelocation);
Intent emailIntent = new Intent(Intent.ACTION_SEND);
// set the type to 'email'
emailIntent .setType("vnd.android.cursor.dir/email");
String to[] = {"asd#gmail.com"};
emailIntent .putExtra(Intent.EXTRA_EMAIL, to);
// the attachment
emailIntent .putExtra(Intent.EXTRA_STREAM, path);
// the mail subject
emailIntent .putExtra(Intent.EXTRA_SUBJECT, "Subject");
startActivity(Intent.createChooser(emailIntent , "Send email..."));
There are two ways to do this
OPTION 1
Intent emailIntent = new Intent(
android.content.Intent.ACTION_VIEW);
//Option 1
Uri data = Uri.parse("mailto:?subject=" + "blah blah subject"
+ "&body=" + "blah blah body" + "&to=" + "sendme#me.com");
emailIntent.setData(data);
startActivity(Intent.createChooser(emailIntent, ""));
Result
OPTION 2
It works perfactly except it wont filter out FTP
//Option 2
emailIntent = new Intent(
android.content.Intent.ACTION_SEND);
emailIntent.setType("message/rfc822");
final String[] toRecipients = new String[] { "sendme#me.com", "", };
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, toRecipients);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "blah blah subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
Html.fromHtml("blah blah body"));
startActivity(Intent.createChooser(emailIntent, ""));
Result
Both ways have minor flaws I show you both ways it is now upto you to pick one.

Intent.ACTION_SENDTO show two options , I want to show only one

Intent.ACTION_SENDTO in shows two options but my clent is asking to remove the gmail option and i don't see a way out please help me
Intent emailIntent =
new Intent(Intent.ACTION_SENDTO,
Uri.fromParts( "mailto",userInput.getText().toString(), null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Press Release");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Please view this press release");
startActivity(Intent.createChooser(emailIntent,"Send mail using..."));
Use
emailIntent.setPackage(PackageName of Email app); before calling startActivity.
You need to set email client package name but, in Samsung devices com.sec.android.email is the default In-Built Mail client, but in HTC it is com.htc.android.mail and so on. So first you need to filter that application and then set to intent. I am adding the solution
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto", userInput.getText().toString(), null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Press Release");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
"Please view this press release");
// Identify the package name of email client and set to intent
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(emailIntent, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName.toLowerCase().contains(".android.email")
|| info.activityInfo.name.toLowerCase().contains(".android.email")) {
emailIntent.setPackage(info.activityInfo.packageName);
// And now call
startActivity(Intent.createChooser(emailIntent, "Send mail using..."));
}
}
}
You should read Android: How to get the native Email clients package name
IF YOU WANT TO REMOVE GMAIL CLIENT FROM LIST create a custom cooser
List<Intent> intents = new ArrayList<Intent>();
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
sendIntent.setType("text/plain");
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(sendIntent, 0);
if (!resInfo.isEmpty()){
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
Intent neededShareIntent = new Intent(android.content.Intent.ACTION_SEND);
neededShareIntent.setType("text/plain");
neededShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Subject");
neededShareIntent.setPackage(packageName);
if (!StringUtils.equals(packageName, "com.google.android.gm")){
intents.add(neededShareIntent);
}
}
Intent chooserIntent = Intent.createChooser(intents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}
Pls test this code and check

intent to share text to email clients (only email clients)

String value = text.getText().toString();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"test#test.test"});
intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
intent.putExtra(Intent.EXTRA_TEXT, value);
startActivity(Intent.createChooser(intent, "Send Email"));
this code runs, but it show a list of applications like notepad (and other notepad app), whatsapp (and several chat app).
I need a list of only email clients. I done a long search but the code is always same.
try the following code with content type:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("plain/text");
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { "some#email.address" });
intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
intent.putExtra(Intent.EXTRA_TEXT, "mail body");
startActivity(Intent.createChooser(intent, ""));
Edit1: Check out this post for sending email directly without opening the email client.

How to send emails from my Android application?

I am developing an application in Android. I don't know how to send an email from the application?
The best (and easiest) way is to use an Intent:
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL , new String[]{"recipient#example.com"});
i.putExtra(Intent.EXTRA_SUBJECT, "subject of email");
i.putExtra(Intent.EXTRA_TEXT , "body of email");
try {
startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(MyActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
Otherwise you'll have to write your own client.
Use .setType("message/rfc822") or the chooser will show you all of the (many) applications that support the send intent.
I've been using this since long time ago and it seems good, no non-email apps showing up. Just another way to send a send email intent:
Intent intent = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject of email");
intent.putExtra(Intent.EXTRA_TEXT, "Body of email");
intent.setData(Uri.parse("mailto:default#example.com")); // or just "mailto:" for blank
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this will make such that when user returns to your app, your app is displayed, instead of the email app.
startActivity(intent);
I was using something along the lines of the currently accepted answer in order to send emails with an attached binary error log file. GMail and K-9 send it just fine and it also arrives fine on my mail server. The only problem was my mail client of choice Thunderbird which had troubles with opening / saving the attached log file. In fact it simply didn't save the file at all without complaining.
I took a look at one of these mail's source codes and noticed that the log file attachment had (understandably) the mime type message/rfc822. Of course that attachment is not an attached email. But Thunderbird cannot cope with that tiny error gracefully. So that was kind of a bummer.
After a bit of research and experimenting I came up with the following solution:
public Intent createEmailOnlyChooserIntent(Intent source,
CharSequence chooserTitle) {
Stack<Intent> intents = new Stack<Intent>();
Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
"info#example.com", null));
List<ResolveInfo> activities = getPackageManager()
.queryIntentActivities(i, 0);
for(ResolveInfo ri : activities) {
Intent target = new Intent(source);
target.setPackage(ri.activityInfo.packageName);
intents.add(target);
}
if(!intents.isEmpty()) {
Intent chooserIntent = Intent.createChooser(intents.remove(0),
chooserTitle);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
intents.toArray(new Parcelable[intents.size()]));
return chooserIntent;
} else {
return Intent.createChooser(source, chooserTitle);
}
}
It can be used as follows:
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("*/*");
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(crashLogFile));
i.putExtra(Intent.EXTRA_EMAIL, new String[] {
ANDROID_SUPPORT_EMAIL
});
i.putExtra(Intent.EXTRA_SUBJECT, "Crash report");
i.putExtra(Intent.EXTRA_TEXT, "Some crash report details");
startActivity(createEmailOnlyChooserIntent(i, "Send via email"));
As you can see, the createEmailOnlyChooserIntent method can be easily fed with the correct intent and the correct mime type.
It then goes through the list of available activities that respond to an ACTION_SENDTO mailto protocol intent (which are email apps only) and constructs a chooser based on that list of activities and the original ACTION_SEND intent with the correct mime type.
Another advantage is that Skype is not listed anymore (which happens to respond to the rfc822 mime type).
To JUST LET EMAIL APPS to resolve your intent you need to specify ACTION_SENDTO as Action and mailto as Data.
private void sendEmail(){
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse("mailto:" + "recipient#example.com")); // You can use "mailto:" if you don't know the address beforehand.
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "My email's subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "My email's body");
try {
startActivity(Intent.createChooser(emailIntent, "Send email using..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(Activity.this, "No email clients installed.", Toast.LENGTH_SHORT).show();
}
}
The solution to this is simple: the android documentation explains it.
(https://developer.android.com/guide/components/intents-common.html#Email)
The most important is the flag: it is ACTION_SENDTO, and not ACTION_SEND
The other important line is
intent.setData(Uri.parse("mailto:")); ***// only email apps should handle this***
By the way, if you send an empty Extra, the if() at the end won't work and the app won't launch the email client.
According to Android documentation. If you want to ensure that your intent is handled only by an email app (and not other text messaging or social apps), then use the ACTION_SENDTO action and include the "mailto:" data scheme. For example:
public void composeEmail(String[] addresses, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
The strategy of using .setType("message/rfc822") or ACTION_SEND seems to also match apps that aren't email clients, such as Android Beam and Bluetooth.
Using ACTION_SENDTO and a mailto: URI seems to work perfectly, and is recommended in the developer documentation. However, if you do this on the official emulators and there aren't any email accounts set up (or there aren't any mail clients), you get the following error:
Unsupported action
That action is not currently supported.
As shown below:
It turns out that the emulators resolve the intent to an activity called com.android.fallback.Fallback, which displays the above message. Apparently this is by design.
If you want your app to circumvent this so it also works correctly on the official emulators, you can check for it before trying to send the email:
private void sendEmail() {
Intent intent = new Intent(Intent.ACTION_SENDTO)
.setData(new Uri.Builder().scheme("mailto").build())
.putExtra(Intent.EXTRA_EMAIL, new String[]{ "John Smith <johnsmith#yourdomain.com>" })
.putExtra(Intent.EXTRA_SUBJECT, "Email subject")
.putExtra(Intent.EXTRA_TEXT, "Email body")
;
ComponentName emailApp = intent.resolveActivity(getPackageManager());
ComponentName unsupportedAction = ComponentName.unflattenFromString("com.android.fallback/.Fallback");
if (emailApp != null && !emailApp.equals(unsupportedAction))
try {
// Needed to customise the chooser dialog title since it might default to "Share with"
// Note that the chooser will still be skipped if only one app is matched
Intent chooser = Intent.createChooser(intent, "Send email with");
startActivity(chooser);
return;
}
catch (ActivityNotFoundException ignored) {
}
Toast
.makeText(this, "Couldn't find an email app and account", Toast.LENGTH_LONG)
.show();
}
Find more info in the developer documentation.
Sending email can be done with Intents which will require no configuration. But then it will require user interaction and the layout will be a bit restricted.
Build and sending a more complex email without user interaction entails building your own client. The first thing is that the Sun Java API for email are unavailable. I have had success leveraging the Apache Mime4j library to build email. All based on the docs at nilvec.
Here is the sample working code which opens mail application in android device and auto-filled with To address and Subject in the composing mail.
protected void sendEmail() {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:feedback#gmail.com"));
intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
I use the below code in my apps. This shows exactly email client apps, such as Gmail.
Intent contactIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", getString(R.string.email_to), null));
contactIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject));
startActivity(Intent.createChooser(contactIntent, getString(R.string.email_chooser)));
This will show you only the email clients (as well as PayPal for some unknown reason)
public void composeEmail() {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi#example.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Body");
try {
startActivity(Intent.createChooser(intent, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(MainActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
}
This is how I did it. Nice and simple.
String emailUrl = "mailto:email#example.com?subject=Subject Text&body=Body Text";
Intent request = new Intent(Intent.ACTION_VIEW);
request.setData(Uri.parse(emailUrl));
startActivity(request);
I used this code to send mail by launching default mail app compose section directly.
Intent i = new Intent(Intent.ACTION_SENDTO);
i.setType("message/rfc822");
i.setData(Uri.parse("mailto:"));
i.putExtra(Intent.EXTRA_EMAIL , new String[]{"test#gmail.com"});
i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
i.putExtra(Intent.EXTRA_TEXT , "body of email");
try {
startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
This function first direct intent gmail for sending email, if gmail is not found then promote intent chooser. I used this function in many commercial app and it's working fine. Hope it will help you:
public static void sentEmail(Context mContext, String[] addresses, String subject, String body) {
try {
Intent sendIntentGmail = new Intent(Intent.ACTION_VIEW);
sendIntentGmail.setType("plain/text");
sendIntentGmail.setData(Uri.parse(TextUtils.join(",", addresses)));
sendIntentGmail.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
sendIntentGmail.putExtra(Intent.EXTRA_EMAIL, addresses);
if (subject != null) sendIntentGmail.putExtra(Intent.EXTRA_SUBJECT, subject);
if (body != null) sendIntentGmail.putExtra(Intent.EXTRA_TEXT, body);
mContext.startActivity(sendIntentGmail);
} catch (Exception e) {
//When Gmail App is not installed or disable
Intent sendIntentIfGmailFail = new Intent(Intent.ACTION_SEND);
sendIntentIfGmailFail.setType("*/*");
sendIntentIfGmailFail.putExtra(Intent.EXTRA_EMAIL, addresses);
if (subject != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_SUBJECT, subject);
if (body != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_TEXT, body);
if (sendIntentIfGmailFail.resolveActivity(mContext.getPackageManager()) != null) {
mContext.startActivity(sendIntentIfGmailFail);
}
}
}
This is the most clean way of sending email on Android.
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf("email#example.com"))
putExtra(Intent.EXTRA_SUBJECT, "Subject")
putExtra(Intent.EXTRA_TEXT, "Email body")
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
You also need to specify in your manifest (outside your application tag) the query for applications that handle email (mailto)
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
If you need to send HTML text in the email body, please replace the "Email body" with your email string, something like this (please beware that Html.fromHtml maybe deprecated this was only for show you how to do it)
Html.fromHtml(
StringBuilder().append("<b>Hello world</b>").toString()
)
simple try this one
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonSend = (Button) findViewById(R.id.buttonSend);
textTo = (EditText) findViewById(R.id.editTextTo);
textSubject = (EditText) findViewById(R.id.editTextSubject);
textMessage = (EditText) findViewById(R.id.editTextMessage);
buttonSend.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String to = textTo.getText().toString();
String subject = textSubject.getText().toString();
String message = textMessage.getText().toString();
Intent email = new Intent(Intent.ACTION_SEND);
email.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
// email.putExtra(Intent.EXTRA_CC, new String[]{ to});
// email.putExtra(Intent.EXTRA_BCC, new String[]{to});
email.putExtra(Intent.EXTRA_SUBJECT, subject);
email.putExtra(Intent.EXTRA_TEXT, message);
// need this to prompts email client only
email.setType("message/rfc822");
startActivity(Intent.createChooser(email, "Choose an Email client :"));
}
});
}
Other solution can be
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.setType("plain/text");
emailIntent.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"someone#gmail.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Yo");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Hi");
startActivity(emailIntent);
Assuming most of the android device has GMail app already installed.
Use this for send email...
boolean success = EmailIntentBuilder.from(activity)
.to("support#example.org")
.cc("developer#example.org")
.subject("Error report")
.body(buildErrorReport())
.start();
use build gradle :
compile 'de.cketti.mailto:email-intent-builder:1.0.0'
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto","ebgsoldier#gmail.com", null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Forgot Password");
emailIntent.putExtra(Intent.EXTRA_TEXT, "this is a text ");
startActivity(Intent.createChooser(emailIntent, "Send email..."));
This method work for me. It open Gmail app (if installed) and set mailto.
public void openGmail(Activity activity) {
Intent emailIntent = new Intent(Intent.ACTION_VIEW);
emailIntent.setType("text/plain");
emailIntent.setType("message/rfc822");
emailIntent.setData(Uri.parse("mailto:"+activity.getString(R.string.mail_to)));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, activity.getString(R.string.app_name) + " - info ");
final PackageManager pm = activity.getPackageManager();
final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
ResolveInfo best = null;
for (final ResolveInfo info : matches)
if (info.activityInfo.packageName.endsWith(".gm") || info.activityInfo.name.toLowerCase().contains("gmail"))
best = info;
if (best != null)
emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
activity.startActivity(emailIntent);
}
/**
* Will start the chosen Email app
*
* #param context current component context.
* #param emails Emails you would like to send to.
* #param subject The subject that will be used in the Email app.
* #param forceGmail True - if you want to open Gmail app, False otherwise. If the Gmail
* app is not installed on this device a chooser will be shown.
*/
public static void sendEmail(Context context, String[] emails, String subject, boolean forceGmail) {
Intent i = new Intent(Intent.ACTION_SENDTO);
i.setData(Uri.parse("mailto:"));
i.putExtra(Intent.EXTRA_EMAIL, emails);
i.putExtra(Intent.EXTRA_SUBJECT, subject);
if (forceGmail && isPackageInstalled(context, "com.google.android.gm")) {
i.setPackage("com.google.android.gm");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} else {
try {
context.startActivity(Intent.createChooser(i, "Send mail..."));
} catch (ActivityNotFoundException e) {
Toast.makeText(context, "No email app is installed on your device...", Toast.LENGTH_SHORT).show();
}
}
}
/**
* Check if the given app is installed on this devuice.
*
* #param context current component context.
* #param packageName The package name you would like to check.
* #return True if this package exist, otherwise False.
*/
public static boolean isPackageInstalled(#NonNull Context context, #NonNull String packageName) {
PackageManager pm = context.getPackageManager();
if (pm != null) {
try {
pm.getPackageInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
return false;
}
Try this:
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
}
The above code will open the users favourite email client prefilled with the email ready to send.
Source
The code below works on Android 10 devices and higher. It also sets the subject, body and recipient(To).
val uri = Uri.parse("mailto:$EMAIL")
.buildUpon()
.appendQueryParameter("subject", "App Feedback")
.appendQueryParameter("body", "Body Text")
.appendQueryParameter("to", EMAIL)
.build()
val emailIntent = Intent(Intent.ACTION_SENDTO, uri)
startActivity(Intent.createChooser(emailIntent, "Select app"))
Kotlin version which only shows Email clients (no contacts etc.):
with(Intent(Intent.ACTION_SEND)) {
type = "message/rfc822"
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf("user#example.com"))
putExtra(Intent.EXTRA_SUBJECT,"YOUR SUBJECT")
putExtra(Intent.EXTRA_TEXT, "YOUR BODY")
try {
startActivity(Intent.createChooser(this, "Send Email with"))
} catch (ex: ActivityNotFoundException) {
// No email clients found, might show Toast here
}
}
import androidx.core.app.ShareCompat
import androidx.core.content.IntentCompat
ShareCompat.IntentBuilder(this)
.setType("message/rfc822")
.setEmailTo(arrayOf(email))
.setStream(uri)
.setSubject(subject)
.setText(message + emailMessage)
.startChooser()
Filtering for 'real' E-Mail Apps is still an issue today. As many people mentioned above, other apps nowadays also report to support the mime-type "message/rfc822". Therefore, this mime-type is not suitable any more to filter for a real E-Mail App.
If you want to send a simple text mail, it is enough to use the the ACTION_SENDTO intent action with the appropriate data type like so:
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, recipients);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, text);
Intent chooser = Intent.createChooser(intent, "Send Mail");
context.startActivity(chooser);
This will filter all available apps for those that support the 'mailto' protocol, which is much more suitable for the purpose of sending an E-mail.
But sadly things become complicated, if you want to send a mail with (multiple) attachments. The ACTION_SENDTO action does not support the EXTRA_STREAM extra on the intent. If you want to use that, you must use the ACTION_SEND_MULTIPLE action, which does not work together with the the data type Uri.parse("mailto:").
For now I found a solution, which consists of the following steps:
Declare that your App wants to query Apps on the device, that support the mailto protocol (important for all Apps since Android 11)
Actually query all Apps, that support the mailto protocol
For each supporting App: Build the intent that you actually want to launch, aiming for that single App
Build the App chooser and launch it
And this is how it looks in code:
Add this to the AndroidManifest:
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
This is the Java code:
/* Query all Apps that support the 'mailto' protocol */
PackageManager pm = context.getPackageManager();
Intent emailCheckerIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
List<ResolveInfo> emailApps = pm.queryIntentActivities(emailCheckerIntent, PackageManager.MATCH_DEFAULT_ONLY);
/* For each supporting App: Build an intent with the desired values */
List<Intent> intentList = new ArrayList<>();
for (ResolveInfo resolveInfo : emailApps) {
String packageName = resolveInfo.activityInfo.packageName;
Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.setPackage(packageName);
intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
intent.putExtra(Intent.EXTRA_EMAIL, recipients);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.putExtra(Intent.EXTRA_STREAM, attachmentUris);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //IMPORTANT to give the E-Mail App access to your attached files
intentList.add(intent);
}
/* Create a chooser consisting of the queried apps only */
Intent chooser = Intent.createChooser(intentList.remove(intentList.size() - 1), "Send Mail");
Intent[] extraIntents = intentList.toArray(new Intent[0]);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
context.startActivity(chooser);
Note: If the itentList only has one item, Android will automatically skip the chooser and run the only App automatically.

Categories

Resources