got crash when try to use intent to send email (Kotlin) - android

I got a crash when I try to send an email using intent with kotlin
here's my function
/**
* intentEmail is called when we need to send email
*
* #param price int
*/
fun intentEmail(price: Int) {
var intent = Intent(Intent.ACTION_SEND)
//intent.putExtra(Intent.EXTRA_EMAIL, addressees)
intent.data= Uri.parse("mailto:")
intent.putExtra(Intent.EXTRA_SUBJECT, "Just Java order for $name")
intent.putExtra(Intent.EXTRA_TEXT, createOrderSummary(price))
if(intent.resolveActivity(packageManager) != null){
startActivity(intent)
}
}
and the crash happens when calling startActivity(intent)
and here's my LogCat

maybe your phone is not accept this intent action. you should use try catch the avoid this crash.
you can also use the phone's other "send mail" app, so that you can find out what's the correct intent.

The issue was in
var intent = Intent(Intent.ACTION_SEND)
when I changed it to
var intent = Intent(Intent.ACTION_SENDTO)
it works fine thanks to #lampenlampen

Related

I want to send a message by email but the Intent doesn't work. Why?

There is a part of my app where I send an email using a button but for some reason the Intent doesn't work and I don't understand why.
binding.IvMail.setOnClickListener {
val email = Intent(Intent.ACTION_SEND)
.setType("text/plain")
.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject))
.putExtra(Intent.EXTRA_TEXT, getString(R.string.email_text))
if (activity?.packageManager?.resolveActivity(email, 0) != null) {
startActivity(email)
}
}
I already searched for other ways to do it but everyone is using Intent.
// try this(JAVA).
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();
}
////For(Kotlin)
sendEmail(recipient, subject, message)
private fun sendEmail(recipient: String, subject: String, message:
String) {
/*ACTION_SEND action to launch an email client installed on your Android device.*/
val mIntent = Intent(Intent.ACTION_SEND)
/*To send an email you need to specify mailto: as URI using
setData() method
and data type will be to text/plain using setType() method*/
mIntent.data = Uri.parse("mailto:")
mIntent.type = "text/plain"
// put recipient email in intent
/* recipient is put as array because you may wanna send email to multiple emails
so enter comma(,) separated emails, it will be stored array*/
mIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(recipient))
//put the Subject in the intent
mIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
//put the message in the intent
mIntent.putExtra(Intent.EXTRA_TEXT, message)
try {
//start email intent
startActivity(Intent.createChooser(mIntent, "Choose Email Client..."))
}
catch (e: Exception){
//if any thing goes wrong for example no email client application or any exception
//get and show exception message
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
}
}
}
You have to use ACTION_SENDTO instead of ACTION_SEND.
See your new code below:
binding.IvMail.setOnClickListener {
val email = Intent(Intent.ACTION_SENDTO) // here you have to use SENDTO
.setType("text/plain")
.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject))
.putExtra(Intent.EXTRA_TEXT, getString(R.string.email_text))
if (activity?.packageManager?.resolveActivity(email, 0) != null) {
startActivity(email)
}
}
Let me know if not solved yet
Your code is fine. If it is not running, it would seem that your if statement is not satisfied and is skipping Intent resolvement.
What you can do to determine the problem is:
Debug if the code blocks are reached, by setting breakpoints and running debug app like this:
Log if the code blocks above are reached, by setting logs and looking for them in logcat tool like this:
You could also look in the Logcat for errors that happened when the intent was being ran.

whatsapp not opening programmatically

have run the code in my phone or just the "else" condition is working.on running the app just displays the "package is not installed"
"Kotlin"
val button = findViewById<Button>(R.id.openwhtaspchat)
button.setOnClickListener {
val uri = Uri.parse("smsto"+"+923354859491")
val intent = Intent(Intent.ACTION_SENDTO,uri)
intent.setPackage("com.whatsapp")
if (intent.resolveActivity(this.packageManager)!=null){
startActivity(intent)
}else{
Toast.makeText(this,"package is not installed",Toast.LENGTH_SHORT).show()
}
when u wanna send something to specific app use
val intent = Intent(Intent.ACTION_SEND, uri)
i'm using always that metode not this one
val intent = Intent(Intent.ACTION_SENDTO, uri)
i'm not sure about kotlin, i use java but Intent are same i think

How to send message to particular whatsapp contact programmatically using intent? [duplicate]

This question already has answers here:
Send text to specific contact programmatically (whatsapp)
(29 answers)
Closed 6 years ago.
I searched various answers but all of them are outdated.
Whenever I tried using send to it only opens contact chooser.
Intent sendIntent = new Intent("android.intent.action.MAIN");
sendIntent.setComponent(new ComponentName("com.whatsapp","com.whatsapp.Conversation"));
sendIntent.putExtra("jid", PhoneNumberUtils.stripSeparators("YOUR_PHONE_NUMBER")+"#s.whatsapp.net");//phone number without "+" prefix
startActivity(sendIntent);
Update:
The aforementioned hack cannot be used to add any particular message, so here is the new approach. Pass the user mobile in international format here without any brackets, dashes or plus sign. Example: If the user is of India and his mobile number is 94xxxxxxxx , then international format will be 9194xxxxxxxx. Don't miss appending country code as a prefix in mobile number.
private fun sendMsg(mobile: String, msg: String){
try {
val packageManager = requireContext().packageManager
val i = Intent(Intent.ACTION_VIEW)
val url =
"https://wa.me/$mobile" + "?text=" + URLEncoder.encode(msg, "utf-8")
i.setPackage("com.whatsapp")
i.data = Uri.parse(url)
if (i.resolveActivity(packageManager) != null) {
requireContext().startActivity(i)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Note: This approach works only with contacts added in user's Whatsapp
account.
You have to set the package name in the Intent like this
intent.setPackage("com.whatsapp");
Full example:
Uri uri = Uri.parse("smsto:" + smsNumber);
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.putExtra("sms_body", smsText);
i.setPackage("com.whatsapp");
startActivity(i);
You just fire the below intent on the click on button:
Uri mUri = Uri.parse("smsto:" + mobile1);
Intent mIntent = new Intent(Intent.ACTION_SENDTO, mUri);
mIntent.setPackage("com.whatsapp");
mIntent.putExtra("sms_body", "The text goes here");
mIntent.putExtra("chat", true);
startActivity(Intent.createChooser(mIntent, ""));
if number available on whatsapp then that particular user chat open and you send your message.If number not available on whatsapp the alert diaolge open in that case.
hope this help you ;-)
Here is solution
private void openWhatsApp(String number) {
String whatsAppMessage = "Hello!";
Uri uri = Uri.parse("smsto:" + number);
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.setPackage("com.whatsapp");
startActivity(i);
}
Call above function and pass number, by which by want to open chat in Whatsapp messenger.
Hope it will work for you. :)

Android Intent Chooser to only show E-mail option

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.

How do I launch the email app with the "to" field pre-filled?

I tried this code which I found here:
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", "testemail#gmail.com", null)); startActivity(intent);
But I get a message on the screen which reads "Unsupported Action". Any ideas of how to get this working?
Try this snippet by dylan:
/* Create the Intent */
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
/* Fill it with Data */
emailIntent.setType("plain/text");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"to#email.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Text");
/* Send it off to the Activity-Chooser */
context.startActivity(Intent.createChooser(emailIntent, "Send mail..."));
Key pieces: using EXTRA_EMAIL for your addresses and using createChooser() in case the user has more than one email client configured.
Did you try
Intent intent = new Intent(
Intent.ACTION_SENDTO,
Uri.parse("mailto:testemail#gmail.com")
);
startActivity(intent);
I think the real problems here are that you're running on the official emulator and your intent isn't matching anything.
From my testing, this is a problem that happens when the intent's URI (from setData()) doesn't match anything and you're running on one of the official Android emulators. This doesn't seem to happen on real devices, so it shouldn't be a real-world problem.
You can use this code to detect when this is going to happen before you launch the intent:
ComponentName emailApp = intent.resolveActivity(getPackageManager());
ComponentName unsupportedAction = ComponentName.unflattenFromString("com.android.fallback/.Fallback");
boolean hasEmailApp = emailApp != null && !emailApp.equals(unsupportedAction);
(The name of the activity that shows the "Unsupported action" action method is com.android.fallback.FallbackActivity.)
For Kotlin use this extention
fun Context.sendEmailTo(email:String){
Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:$email")
startActivity(this)
}
}

Categories

Resources