androidandroid-intentandroid-intent-chooser

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


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?


Solution

  • 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.