18

I'm writing an app targeted at Lollipop and above. This is my first Android app.

I'm trying to get a list of all the accounts that are associated with the device. Here is my code:

public void getAllContactsAccounts(Context context){
    AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
    Account[] accounts = accountManager.getAccounts();
    System.out.println("PrintingAccounts: " + accounts.length);
    for(Account a : accounts){
        System.err.println("AccountName: " + a.name);
    }
}

The array from accountManager.getAccounts() ends up having a length of 0, and nothing happens.

I can't figure out how to fix this. I've added the necessary permissions (plus a few others), no security exception happens, the app runs fine, but it just can't seem to retrieve the accounts.

Any advice on what I can do here?

craigmiller160
  • 5,751
  • 9
  • 41
  • 75
  • I copied your code and ran it on my Lollipop device. The two Google accounts I have on the device are listed. When you go to Settings --> Accounts on your phone, do you see accounts listed there? – Bob Snyder Jan 28 '16 at 00:53
  • This could be because of the new concept of 'Dangerous permissions' in Android M. Check this answer for more information: http://stackoverflow.com/questions/34561188/targetsdkversion-23-returns-0-length-array-via-accountmanager-getaccounts – Pascal Feb 04 '16 at 08:02
  • Pascals Comment is correct, Android now requires explicitly in your activity to request permission. As a user this makes sense as it improves security. When user has granted a permission the Account Manager Array will not be empty. – MG Developer Sep 16 '18 at 22:39

4 Answers4

27

From Android 8.0, GET_ACCOUNTS is no longer sufficient to access the Accounts on device.

Based on the documentation:

In Android 8.0 (API level 26), apps can no longer get access to user accounts unless the authenticator owns the accounts or the user grants that access. The GET_ACCOUNTS permission is no longer sufficient. To be granted access to an account, apps should either use AccountManager.newChooseAccountIntent() or an authenticator-specific method. After getting access to accounts, an app can call AccountManager.getAccounts() to access them.

You can check this link for usage of AccountManager.newChooseAccountIntent()

  • How Android knows if the authenticator owns the accounts? I made two apps with different application IDs and account types but somehow one was being able to retrieve the account of the other. – Allan Veloso Feb 15 '19 at 16:40
  • As for me, just adding READ_CONTACTS permission was enough – Val Martinez Jul 14 '22 at 19:56
18

For some reason, I had to request "android.permission.READ_CONTACTS" too to access the accounts list. Seems like required permissions are:

android.permission.READ_CONTACTS

android.permission.GET_ACCOUNTS

Thomas Thomas
  • 824
  • 1
  • 9
  • 21
  • Same thing here. I didn't found any documentation on this point. Even the Account tutorial from android.com doesn't mention this (https://developer.android.com/training/id-auth/identify). Is this a workaround for an issue I do not understand ? – mgueydan May 03 '20 at 19:12
  • Awesome, thank you. This did fix the issue on my end. – LaoDa581 May 31 '23 at 16:19
9

Since the SdkTarget 23 and above(Marshmallow 6.0) you need to ask the user for permissions to access via run-time

 int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 0;
    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(this,
            android.Manifest.permission.GET_ACCOUNTS)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                android.Manifest.permission.GET_ACCOUNTS)) {

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

        } else {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.GET_ACCOUNTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);
    }
}
    String possibleEmail="";
    try{
        possibleEmail += "************* Get Registered Gmail Account *************\n\n";
        Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");

        for (Account account : accounts) {

            possibleEmail += " --> "+account.name+" : "+account.type+" , \n";
            possibleEmail += " \n\n";

        }
    }


     Log.i("EXCEPTION", "mails: " + possibleEmail);

a snippet that is in onCreate() use for reference only

Here's a reference of these changes and some Documentation

RedKlouds
  • 99
  • 2
  • 6
-1

Need to add extra android.permission.READ_CONTACTS permission for Android 8+

Goooler
  • 34
  • 6