45

I want to allow the user to provide me their email address without typing it in. Ideally, there'd be a text field where the user could either type an email address or push a button to autofill it.

In an earlier question, Roman Nurik suggests using an AccountManager to handle this, but that requires my app to use the GET_ACCOUNTS privilege; my app could then access all of the user's accounts on the device, including their Facebook/Twitter accounts. That permission seems way too broad for what I want.

Is there a nicer way to handle this that doesn't require granting my app such a heavy duty permission?

3
  • 2
    One thing I noticed after posing the question is that the GET_ACCOUNTS privilege is often hidden in the "More Details" section; it doesn't show up in the list of privileges above the fold. So most users won't notice if you ask for this permission. Commented Jul 7, 2011 at 4:12
  • Do you really think GET_ACCOUNTS is so heavy? You need it for GCM (at least if you want to support < v4.0.4).
    – ostergaard
    Commented Aug 19, 2013 at 2:45
  • Do you need to request this permission too? Can user disable it? Commented Jan 3, 2017 at 16:22

5 Answers 5

123

I know I'm way too late, but this might be useful to others.

I think the best way to auto-populate an email field now is by using AccountPicker

If your app has the GET_ACCOUNTS permission and there's only one account, you get it right away. If your app doesn't have it, or if there are more than one account, users get a prompt so they can authorize or not the action.

Your app needs to include the Google Play Services auth library com.google.android.gms:play-services-auth but it doesn't need any permissions.

This whole process will fail on older versions of Android (2.2+ is required), or if Google Play is not available so you should consider that case.

Here's a basic code sample:

    private static final int REQUEST_CODE_EMAIL = 1;
    private TextView email = (TextView) findViewById(R.id.email);

    // ...

    try {
        Intent intent = AccountPicker.newChooseAccountIntent(null, null,
                new String[] { GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE }, false, null, null, null, null);
        startActivityForResult(intent, REQUEST_CODE_EMAIL);
    } catch (ActivityNotFoundException e) {
        // TODO
    }

    // ...

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE_EMAIL && resultCode == RESULT_OK) {
            String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
            email.setText(accountName);
        }
    }
13
  • I like this approach, it works on 4.0.3 tablet I use and I will surely test on other devices :) Thanks! Commented Jan 29, 2014 at 10:29
  • 19
    There are a lot of devices that don't comply the requirements set by Google and therefore don't have access to G-apps, including Google Play. They have to install apps from alternate markets or by downloading APK files. Even if it's a small percentage, you must always consider all scenarios in your apps. Commented Mar 14, 2014 at 17:06
  • 2
    Tested on 4 different devices and works [from Android 4.x to Android 5.1] and this approach is working on all of them: Galaxy Note 4, HTC One X+, Sony Xperia and Nexus7 tablet. Thanks!
    – A. Masson
    Commented Sep 18, 2015 at 6:02
  • 2
    @semicircle21 For some reason, only permissions that are added on are internet-related stuff and "prevent phone from sleeping". Not something related to contacts/accounts. I've tested it now on multiple Android devices and versions. Also, BTW, as of Android 6, you can use : AccountManager.newChooseAccountIntent Commented May 15, 2016 at 9:13
  • 1
    To be exact, you need to include com.google.android.gms:play-services-auth:17.0.0
    – CamHart
    Commented Jul 21, 2019 at 9:55
19
+50

Indeed, not only can't you do this without GET_ACCOUNTS, the information you want only exists in the user's (Google) account data.

On my Sprint phone, the 'owner' address sprint assigns is [email protected], and that can be seen using getprop from a shell. But that's not my primary email address, or even one I ever use/check. What you want is my gmail address, and that's stored in the Android account data.

Actually, you want one of the two — which is another reason you need GET_ACCOUNTS. If you're going to ask for my email address, you need to let me select among the two @gmail.com accounts I have configured on the device. I know which one is my 'preferred' one (although even that's contextual), but AFAIK neither is considered by the system to be more 'primary' or 'default' than the other.

0

An alternative approach might be to find the Google username associated with the device, from which you can reconstruct a [email protected] address, but that still requires use of the AccountManager. See Accessing Google Account Id /username via Android.

3
  • 1
    I don't think that's even an alternative approach; that's no different from Roman's suggestion (which I linked in the original question). It requires me to GET_ACCOUNTS which is just too big of a security privilege IMO Commented Jul 1, 2011 at 23:28
  • 3
    Well, then, I think the answer to your question is No. Commented Jul 2, 2011 at 19:26
  • Don't use this, some people have custom domains.
    – Ajay
    Commented Sep 6, 2019 at 18:19
0

As the accepted answer is deprecated, you can use new approach:

val result = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {

    if (it.resultCode == Activity.RESULT_OK) {
        val accountName = it.data?.getStringExtra(AccountManager.KEY_ACCOUNT_NAME)
    }
}

val options = AccountChooserOptions.Builder()       
    .setAlwaysShowAccountPicker(true)
    .build()

result.launch(AccountPicker.newChooseAccountIntent(options))
-8

There is no nice way to access the user's account (e-mail) information without asking for the GET_ACCOUNTS permission. :-)

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.