How to show all E-mail applications in a chooser in Android?

498 Views Asked by At

I need to show an E-mail chooser with all installed E-mail apps to the user to select an App and check E-mails (not compose). I'm using the below code.

val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(Intent.createChooser(intent, "Open E-mail"))

But it directly opens the default E-mail app without a chooser. How can I show all supported/installed E-mail apps in the chooser?

2

There are 2 best solutions below

0
Parniyan On BEST ANSWER

I had this problem opening a chooser for only email apps, but I couldn't find a working solution. I wanted the chooser to filter only installed email apps and exclude other applications that can send messages, like social media apps or Bluetooth. Additionally, the solutions I found online only allowed me to send new emails and didn't open the inbox of the email application.

After going through multiple solutions on Stack Overflow, I found a working suggestion that combines different approaches. Here's the solution:

First, add the following code to your AndroidManifest.xml file:

<queries>
    <intent>
        <action android:name="android.intent.action.VIEW"/>
        <data android:scheme="mailto"/>
    </intent>
    <intent>
        <action android:name="android.intent.action.SEND"/>
        <data android:scheme="mailto"/>
    </intent>
</queries>

This code allows your app to query and interact with email apps installed on the device.

Next, implement the openMailbox function:

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.net.Uri

fun Context.openMailbox(chooserTitle: String) {
    val mContext: Context = applicationContext
    val emailIntent = Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"))
    val resInfo = mContext.packageManager.queryIntentActivities(emailIntent, 0)
    if (resInfo.isNotEmpty()) {
        // First create an intent with only the package name of the first registered email app
        // and build a picker based on it
        val intentChooser = mContext.packageManager.getLaunchIntentForPackage(
            resInfo.first().activityInfo.packageName
        )
        val openInChooser = Intent.createChooser(intentChooser, chooserTitle)
        // Then create a list of LabeledIntent for the rest of the registered email apps
        val packageManager = mContext.packageManager
        val emailApps = resInfo.toLabeledIntentArray(packageManager)
        // Add the rest of the email apps to the picker selection
        openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailApps)
        openInChooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        startActivity(mContext, openInChooser, null)
    } else {
        // Handle the case where no email apps are installed
    }
}

private fun List<ResolveInfo>.toLabeledIntentArray(packageManager: PackageManager): Array<LabeledIntent> =
    map {
        val packageName = it.activityInfo.packageName
        val intent = packageManager.getLaunchIntentForPackage(packageName)
        LabeledIntent(intent, packageName, it.loadLabel(packageManager), it.icon)
    }.toTypedArray()

You can call the openMailbox function on a button click or anywhere you want to trigger the intent.

This solution ensures that only installed email apps are displayed in the chooser, allowing users to open their preferred email app and access their inbox directly.

I hope this helps you solve the issue of opening a chooser with filtered email apps in your Android application.

1
Blundell On

Use ACTION_SEND:


    val intent = Intent(Intent.ACTION_SEND).apply {
        // The intent does not have a URI, so declare the "text/plain" MIME type
        type = "text/plain"
        putExtra(Intent.EXTRA_EMAIL, arrayOf("[email protected]")) // recipients
        putExtra(Intent.EXTRA_SUBJECT, "Email subject")
        putExtra(Intent.EXTRA_TEXT, "Email message text")
    }
    startActivity(intent)

https://developer.android.com/training/basics/intents/sending


Also your original code has:

startActivity(intent)
startActivity(Intent.createChooser(intent, "Open E-mail")

Drop the duplication


Don't forget to account for the scenario where zero app's match your intent:

try {
    startActivity(intent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

If the system identifies more than one activity that can handle the intent, it displays a dialog (sometimes referred to as the "disambiguation dialog") for the user to select which app to use. If there is only one activity that handles the intent, the system immediately starts it.

createChooser is for when you want the user to potentially select a different app each time. For example when sharing an image, perhaps one time they want to use Signal and another time WhatsApp or Twitter.