Right now for sdk 30, I am successfully able to send and attach a json file to some email client when using ACTION_SEND. However there are two issues that I noticed when using ACTION_SEND:
it shows ALL apps, not just email apps, which is what I want
it does NOT show the intent with title/text for the user to choose an email app. I do NOT just want to use a Toast message
I think this can be solved using ACTION_SENDTO instead, but then I won't be able to attach my file, so that actually won't work.
With this said, I would like to solve either point 1 or 2 (preferably point 1), if not both.
Here is what I have:
private void sendToEmail(String emailAddress, String filePath) {
File file = new File(filePath);
file.setReadOnly();
String[] to = { emailAddress };
Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", file);
grantUriPermission("com.my.package", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intent = new Intent(Intent.ACTION_SEND);
//intent.setData(Uri.parse("mailto:")); // this does NOT work for the above action type
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_SUBJECT, "Your backup file");
intent.putExtra(Intent.EXTRA_TEXT, "Your data for your backup is attached to the file " + BACKUP_NAME + ".");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("message/rfc822");
// this does NOT create the below title for ACTION_SEND, as per documentation for createChooser()
Intent chooser = Intent.createChooser(intent, "Pick an email app to send attachment: " + BACKUP_NAME);
if (chooser.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
}
I need to send app invitation message from my app to friends via whatsapp,facebook,hike,... with the message and playstore link.I have seen this kind of invitations in other apps like hike,whatscall,... like the
attached image
I want to send exactly the same kind of message with the playstore link and app logo for my app also and it should be shared using all the available sharing option in users mobile.In my application i have included a inform friends menu and on clicking on that this function should work.I have seen firebase app invite examples but it needs google-services.json and i think it will only send text message from users email,I am not sure about that.
Sending text msg or image or both via app can be done using Action_send intent. The following code should work for your requirement.
void shareImageWithText(){
Uri contentUri = Uri.parse("android.resource://" + getPackageName() + "/drawable/" + "ic_launcher");
StringBuilder msg = new StringBuilder();
msg.append("Hey, Download this awesome app!");
msg.append("\n");
msg.append("https://play.google.com/store/apps/details?id=Your_Package_Name"); //example :com.package.name
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
shareIntent.setType("*/*");
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, msg.toString());
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
try {
startActivity(Intent.createChooser(shareIntent, "Share via"));
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), "No App Available", Toast.LENGTH_SHORT).show();
}
}
}
I'm developing an application that can send message through whatsapp. I have implemented it by following this answer but it only works for contacts that on my contact list. It keeps error when i try to send message to contacts that are not in my contact list although the user already registered on whatsapp using that number (contact). Here is the message from whatsapp:
here is my code:
try {
Uri uri = Uri.parse("smsto: " + smsNumber);
//Timber.e("smsNumber %s", uri.toString());
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.setPackage("com.whatsapp");
startActivity(Intent.createChooser(i, ""));
} catch (Exception e) {
Toast.makeText(this, "WhatsApp not Installed", Toast.LENGTH_SHORT).show();
}
is there any solutions ?
you can send via WhatsApp API even if he is not in your contact
String whatsappUrl = String.format("https://api.whatsapp.com/send?phone=%s&text%s",PhoneNumber,msg);
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(whatsappUrl));
browserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
p_context.startActivity(browserIntent);
I've got an intent that uses FileProvider to read from internal file storage for my app to send a file via email (or similar apps). The code works great everywhere apparently except for Gmail, which strangely adds a version of the provider path itself to the list of addressees of the email.
This is the code generating the intent:
public static Intent getSendIntent(Uri uri) {
final Intent i = new Intent(Intent.ACTION_SEND);
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
i.setDataAndType(uri, "message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL, new String[] { "my#email.com" });
i.putExtra(Intent.EXTRA_SUBJECT, "Export");
i.putExtra(Intent.EXTRA_TEXT, "See the attached...");
i.putExtra(Intent.EXTRA_STREAM, uri);
return i;
}
This is the code to start the activity:
File file = new File(getFilesDir(), filename);
Uri uri = FileProvider.getUriForFile(MainActivity.this, "com.example.myapplication.provider", file);
Intent i = Utils.getSendIntent(uri);
try {
startActivity(Intent.createChooser(i, "Send file..."));
} catch (Exception e) {
Log.d(TAG, "failed to start send activity: " + e.getMessage());
Toast.makeText(MainActivity.this, "No suitable activity found for export.", Toast.LENGTH_SHORT).show();
}
Works well in Slack, Evernote, etc. but in Gmail in addition to the email address I've provided, another addressee in this kind of format is added:
//com.example.myapplication.provider/my_files/filefile.csv
which prevents the email from sending until it's manually removed from the message. Everything else about the message is as expected.
Any clue how to prevent this?
The following Captain Obvious solution resolved the problem.
Replace:
i.setDataAndType(uri, "message/rfc822");
with:
i.setType("message/rfc822");
since, as #CommonsWare's question inferred, the file content isn't itself in rfc822 format.
My app integrates e-mail where the user can submit a bug report, feedback, etc. from the app directly. I'm using the application/octet-stream as the SetType for the Intent. When you go to submit the e-mail you get the content chooser and it shows various items from Evernote, Facebook, E-mail, etc.
How can I get this chooser to only show E-mail so as not to confuse the user with all these other items that fit the content chooser type?
Thank you.
To solve this issue simply follow the official documentation. The most important consideration are:
The flag is ACTION_SENDTO, and not ACTION_SEND.
The setData of method of the intent,
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
If you send an empty Extra, the if() at the end won't work and the app won't launch the email client.
This works for me. 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);
}
}
https://developer.android.com/guide/components/intents-common.html#Email
I am presuming that you are using the ACTION_SEND Intent action, since you did not bother to actually state what you're using, but you agreed with #Aleadam's comment.
I'm using the application/octet-stream as the SetType for the Intent.
Nothing in that sentence limits things to email.
ACTION_SEND is a generic Intent action that can be supported by any application that wants to. All you do is indicate what data you are sharing and the MIME type of that data -- from there, it is up to the user to choose from available activities.
As #Jasoon indicates, you can try message/rfc822 as the MIME type. However, that is not indicating "only offer email clients" -- it indicates "offer anything that supports message/rfc822 data". That could readily include some application that are not email clients.
If you specifically want to send something by email, integrate JavaMail into your app, or write an email forwarding script on your Web server and invoke it, or something. If you use ACTION_SEND, you are implicitly stating that it is what the user wants that matters, and you want the user to be able to send such-and-so data by whatever means the user chooses.
Just struggled with this problem while implementing a Magic Link feature, a chooser intent for all installed email apps:
Chooser Intent Screenshot
private void openEmailApp() {
List<Intent> emailAppLauncherIntents = new ArrayList<>();
//Intent that only email apps can handle:
Intent emailAppIntent = new Intent(Intent.ACTION_SENDTO);
emailAppIntent.setData(Uri.parse("mailto:"));
emailAppIntent.putExtra(Intent.EXTRA_EMAIL, "");
emailAppIntent.putExtra(Intent.EXTRA_SUBJECT, "");
PackageManager packageManager = getPackageManager();
//All installed apps that can handle email intent:
List<ResolveInfo> emailApps = packageManager.queryIntentActivities(emailAppIntent, PackageManager.MATCH_ALL);
for (ResolveInfo resolveInfo : emailApps) {
String packageName = resolveInfo.activityInfo.packageName;
Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName);
emailAppLauncherIntents.add(launchIntent);
}
//Create chooser
Intent chooserIntent = Intent.createChooser(new Intent(), "Select email app:");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailAppLauncherIntents.toArray(new Parcelable[emailAppLauncherIntents.size()]));
startActivity(chooserIntent);
}
There is a way more generic to do that, working with any MIME type.
See this post: How to customize share intent in Android?
It is possible to limit the choices of an intent chooser to just a few options. The code in the answer to this question is a good example. In essence, you would have to create a List of LabeledIntents to provide to the intent chooser, that will then include it in its list. Note that this solution works not on exclusion (certain apps are excluded while the rest remain) but instead you have to pick which apps to display. Hope it helps!
It works on all devices. It will show only Email Apps
public static void shareViaMail(Activity activity, String title, String body, String filePath) {
Uri URI = Uri.parse("file://" + filePath);
final Intent emailIntent = new Intent(Intent.ACTION_VIEW);
emailIntent.setData(Uri.parse("mailto:"));
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"contact#brightsociety.com"});
if (URI != null) {
emailIntent.putExtra(Intent.EXTRA_STREAM, URI);
}
try {
activity.startActivity(emailIntent);
} catch (Exception e) {
((BaseActivity) activity).showToast("Gmail App is not installed");
e.printStackTrace();
}
}
Kotlin Answer
If you need to show only email apps and then you want to open only inbox (not open new email writing), you need to do A and B:
A) Add below code in your AndroidManifest.xml file for Android 11 because of package visibility update of Android 11 :
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
<intent>
<action android:name="android.intent.action.CHOOSER" />
</intent>
</queries>
B) Use below function to show email chooser:
// Show email app list.
fun showEmailAppList() {
// Email app list.
val emailAppLauncherIntents: MutableList<Intent?> = ArrayList()
// Create intent which can handle only by email apps.
val emailAppIntent = Intent(Intent.ACTION_SENDTO)
emailAppIntent.data = Uri.parse("mailto:")
// Find from all installed apps that can handle email intent and check version.
val emailApps = packageManager.queryIntentActivities(
emailAppIntent,
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) 0 else PackageManager.MATCH_ALL
)
// Collect email apps and put in intent list.
for (resolveInfo in emailApps) {
val packageName = resolveInfo.activityInfo.packageName
val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
emailAppLauncherIntents.add(launchIntent)
}
// Create chooser with created intent list to show email apps of device.
val chooserIntent = Intent.createChooser(Intent(), "OPEN EMAIL APP")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailAppLauncherIntents.toTypedArray())
startActivity(chooserIntent)
}
Result:
It works on all devices.It will show only Email Apps
public static void shareViaMail(Activity activity, String title, String body, String filePath) {
Uri URI = Uri.parse("file://" + filePath);
final Intent emailIntent = new Intent(Intent.ACTION_VIEW);
emailIntent.setData(Uri.parse("mailto:"));
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"xyz#gmail.com"});
/*if you want to attach something*/
if (URI != null) {
emailIntent.putExtra(Intent.EXTRA_STREAM, URI);
}
try {
activity.startActivity(emailIntent);
} catch (Exception e) {
((BaseActivity) activity).showToast("Gmail App is not installed");
e.printStackTrace();
}
}
Solution is very simple:
Intent testIntent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.parse("mailto:?subject=" + "blah blah subject" + "&body=" + "blah blah body" + "&to=" + "sendme#me.com");
testIntent.setData(data);
startActivity(testIntent);
See: http://www.gaanza.com/blog/email-client-intent-android/
After a lot of searching and testing, I finally found a perfect solution. Thanks to the Open source developer, cketti for sharing his/her concise and neat solution.
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
}
And this is the link to his/her gist.