3

So in my app I have a button to open gmail so the user can check for a verification code.

I use this code to open gmail:

val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
try {
    activity?.startActivity(intent)
} catch (e: Exception) {
    activity?.let {
        AlertDialog.Builder(it)
            .setTitle("Email App Not Found")
            .show()
    }
}

It is working great to launch gmail, however what I need is for the back button to come back to my app.

Currently when I hit the back button from gmail it will minimize my app, and then reopening my app just reopens gmail with no way to get back to my app without fully closing and reopening it.

Is there a way to override the back button to get back to my app from gmail?

EraftYps
  • 778
  • 1
  • 6
  • 18
Quinn
  • 7,072
  • 7
  • 39
  • 61
  • Use ACTION_SENDTO with "mailto:" data scheme to ensure that the intent is handled by email apps only. See https://developer.android.com/guide/components/intents-common.html#Email – EraftYps Jun 16 '20 at 20:17

5 Answers5

8

If you don't want the e-mail app to be opened in the current stack, add this flag:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Cristan
  • 12,083
  • 7
  • 65
  • 69
1

So in my app I have a button to open gmail so the user can check for a verification code

You have an incorrectly-constructed Intent to open an email client. The documentation specifically points out that how you are using CATEGORY_APP_EMAIL is incorrect:

NOTE: This should not be used as the primary key of an Intent, since it will not result in the app launching with the correct action and category. Instead, use this with makeMainSelectorActivity(java.lang.String,java.lang.String) to generate a main Intent with this category in the selector.

If you are trying to start the same activity that the launcher does, you would need an ACTION_MAIN/CATEGORY_LAUNCHER Intent, with a selector Intent that attempts to restrict the choices to email apps.

Is there a way to override the back button to get back to my app from gmail?

Not generally. How an app responds to the system BACK button is up to the developers of that app. It is possible that addressing the Intent problem will improve this behavior as a side effect.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
0

I gave your code a try and it works on Emulator Pixel 2. So, there are a couple of things you may check.

The first one to see if you have some code that invokes something like finish() that clears this activity from the back stack especially in onPause() and onStop().

The second to check if you're enabling Don't Keep activities at the device Developer Options.. that will destroy the current activity before going to Gmail so that you can't return back.

Zain
  • 37,492
  • 7
  • 60
  • 84
0

I had the exact same problem and found out there are differences between different mail apps. When I pick Samsung Mail from the chooser I do not encounter this problem and I am able to return to my app by pressing back. However, when I choose Gmail from the chooser I encounter the same problem as you describe.

I have tried nearly every possible solution I could find on StackOverflow, but this seemed to be the only working answer: https://stackoverflow.com/a/28190257/11642110 I will post the code in case the link dies.

Java:

Intent emailIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"));
PackageManager packageManager = getPackageManager();
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(emailIntent, 0);

if (resolveInfoList.size() > 0) {
    ResolveInfo resolveInfo = resolveInfoList.get(0);

    // First create an intent with only the package name of the first registered email app
    // and build a picked based on it
    Intent chooserIntent = Intent.createChooser(packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName), "");

    // Then create a list of LabeledIntent for the rest of the registered email apps
    List<LabeledIntent> intentList = new ArrayList<>();

    for (int i = 1; i < resolveInfoList.size(); i++) {
        // Extract the label and repackage it in a LabeledIntent
        resolveInfo = resolveInfoList.get(i);
        String packageName = resolveInfo.activityInfo.packageName;
        Intent intent = packageManager.getLaunchIntentForPackage(packageName);
        intentList.add(new LabeledIntent(intent, packageName, resolveInfo.loadLabel(packageManager), resolveInfo.icon));
    }

    LabeledIntent[] extraIntents = intentList.toArray(new LabeledIntent[0]);
            
    // Add the rest of the email apps to the picker selection
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
    startActivity(chooserIntent);
}

Kotlin:

val emailIntent = Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"))
val packageManager = context?.packageManager
val resolveInfoList = packageManager?.queryIntentActivities(emailIntent, 0)

if (!resolveInfoList.isNullOrEmpty()) {
    var resolveInfo = resolveInfoList[0]

    // First create an intent with only the package name of the first registered email app
    // and build a picked based on it
    val chooserIntent = Intent.createChooser(packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName), "")

    // Then create a list of LabeledIntent for the rest of the registered email apps
    val intentList: MutableList<LabeledIntent> = ArrayList()

    for (i in 1 until resolveInfoList.size) {
         // Extract the label and repackage it in a LabeledIntent
         resolveInfo = resolveInfoList[i]
         val packageName = resolveInfo.activityInfo.packageName
         val intent = packageManager.getLaunchIntentForPackage(packageName)
         intentList.add(LabeledIntent(intent, packageName, resolveInfo.loadLabel(packageManager), resolveInfo.icon))
    }

    // Add the rest of the email apps to the picker selection
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toTypedArray())
    startActivity(chooserIntent)
}
Mr. Robot
  • 397
  • 1
  • 14
0

A workaround that covers also Android 11. First put at the manifest:

<manifest
....
<queries>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="image/jpeg" />
        </intent>
    </queries>
....
<application
...
<application/>
<manifest/>

Then at code:

try {
                // Workaround for not coming back from GMail app.
                val emailIntent = Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"))
                val packageManager = context?.packageManager
                val resolveInfoList = packageManager?.queryIntentActivities(emailIntent, 0)

                if (!resolveInfoList.isNullOrEmpty()) {
                    var resolveInfo = resolveInfoList[0]

                    // First create an intent with only the package name of the first registered email app
                    // and build a pick based on it.
                    val chooserIntent = Intent.createChooser(packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName),
                        "Open email app:"
                    )

                    // Then create a list of LabeledIntent for the rest of the registered email apps
                    val intentList: MutableList<LabeledIntent> = ArrayList()

                    for (i in 1 until resolveInfoList.size) {
                        // Extract the label and repackage it in a LabeledIntent
                        resolveInfo = resolveInfoList[i]
                        val packageName = resolveInfo.activityInfo.packageName
                        val intent = packageManager.getLaunchIntentForPackage(packageName)
                        intentList.add(
                            LabeledIntent(
                                intent,
                                packageName,
                                resolveInfo.loadLabel(packageManager),
                                resolveInfo.icon
                            )
                        )
                    }

                    // Add the rest of the email apps to the picker selection
                    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toTypedArray())
                    startActivity(chooserIntent)
                } else {
                    // If there are no email providers show a banner that no apps can complete the action
                    // making an intent that is not meaningful.
                    val intent = Intent(Intent.ACTION_MAIN)
                    intent.type = "fgthy/dfrtg"
                    startActivity(Intent.createChooser(intent, " "))
                }
            } catch (e: Exception) {
                Toast.makeText(requireActivity(), "Message", Toast.LENGTH_LONG).show()
            }

There is still an issue with android 11 though that is OS related where the picker shows only 3 email apps even if the user has more than 3.

Farmaker
  • 2,700
  • 11
  • 16