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?

Community
  • 1
  • 1
Dan Fabulich
  • 37,506
  • 41
  • 139
  • 175
  • 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. – Dan Fabulich Jul 07 '11 at 04: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 Aug 19 '13 at 02:45
  • Do you need to request this permission too? Can user disable it? – rupinderjeet Jan 03 '17 at 16:22

4 Answers4

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);
        }
    }
CamHart
  • 3,825
  • 7
  • 33
  • 69
Jorge Cevallos
  • 3,667
  • 3
  • 25
  • 37
  • I like this approach, it works on 4.0.3 tablet I use and I will surely test on other devices :) Thanks! – Henrique de Sousa Jan 29 '14 at 10:29
  • Doesn't make sense to say if Google Play isn't activated it won't work because every app is downloaded through Google play, unless the person downloaded the apk from browser. But good answer tho +1 – Luis Pena Mar 02 '14 at 20:18
  • 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. – Jorge Cevallos Mar 14 '14 at 17:06
  • Keep in mind that Google play services might be out of date and even misconfigured. – Igor Čordaš Jul 01 '14 at 16:07
  • The requestCode returned to onActivityResult is for some reason always 65644 and not what is sent in startActivityForResult (1 in above code). I just ignored the returnCode and checked the data for desired data. – A.J. Dec 22 '14 at 20:09
  • Thanks so much for this. I know it's a bit of an old answer, but it would be helpful to me (and probably others) to know what would happen on a device that has Google Play, but where the app was installed through another marketplace like Amazon? If the user does not have Google play, is that caught under the ActivityNotFoundException section? – Nicholas Apr 14 '15 at 12:48
  • @Nicholas It doesn't matter if the app was installed through Amazon, direct download or any other way. As long as Google Play is there and the OS is Android 2.2+ then it will work. If those requirements are not met then an ActivityNotFoundException will be triggered. – Jorge Cevallos Apr 17 '15 at 17:15
  • 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 Sep 18 '15 at 06:02
  • Hmm, I feel like something is wrong here. I tried it on my nexus 5 with android 6 with only 1 account. When I call activity for result, it immediately return result with no interaction with user. So user is not aware of it. That way I can steal his email without him even noticing it. What a hell? – Srneczek Dec 05 '15 at 17:30
  • Where there is more than one account name, is there any way of just grabbing the first account name, without the selection dialog appearing (though with some sort of authorisation dialog first, if the app does not have GET_ACCOUNTS permission)? – drmrbrewer Jan 06 '16 at 10:07
  • "Your app needs to include the Google Play Services but it doesn't need any permissions." - This sentence may lead to misunderstanding. Because the permissions are automatically added: http://stackoverflow.com/questions/30658439/why-are-permissions-being-automatically-added-to-my-androidmanifest-when-includi – semicircle21 Apr 28 '16 at 12:32
  • 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 – android developer May 15 '16 at 09:13
  • 1
    To be exact, you need to include `com.google.android.gms:play-services-auth:17.0.0` – CamHart Jul 21 '19 at 09:55
19

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 myusername@sprintpcs.com, 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.

FeRD
  • 1,699
  • 15
  • 24
0

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

Community
  • 1
  • 1
Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • 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 – Dan Fabulich Jul 01 '11 at 23:28
  • 3
    Well, then, I think the answer to your question is No. – Graham Borland Jul 02 '11 at 19:26
  • Don't use this, some people have custom domains. – Ajay Sep 06 '19 at 18:19
-8

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

sparkymat
  • 9,938
  • 3
  • 30
  • 48