Android 8.0 Oreo - Accounts

泄露秘密 提交于 2019-12-04 06:44:27

Using "android.permission.READ_CONTACTS" permission, and

    Account[] accounts = AccountManager.get(getContext())
.getAccountsByType("com.google") 

working again in android Oreo

As you already said, there's no way to read other accounts if the user didn't give you the permission to do so. The permission now is provided not only with the run-time permission but even with the account picker, i.e. an account is visible to your app only if the user selected the account after you called the account picker. This new restriction is exactly to avoid what you are trying to do: read all user accounts. There's no solution to your problem, the only thing you can do is to present the picker to the user and let him select all the accounts, not the best user experience however.

Edit: starting from Google Play Services 11.6 there's now a new method requestGoogleAccountsAccess() to get all Google accounts.

To get the installed google accounts on a device running Oreo+ (8+) with this code

 Account[] accounts = AccountManager.get(getContext()).getAccountsByType("com.google")

You need to first call

https://developers.google.com/android/reference/com/google/android/gms/auth/GoogleAuthUtil.html#requestGoogleAccountsAccess(android.content.Context)

Please add the following dependency first

com.google.android.gms:play-services-auth:16.0.0

The call requestGoogleAccountsAccess() throws an exception which you can cast (after checking) to UserRecoverableAuthException and get an intent from it to start with startActivityForResult

Here is some example code, working on Android Oreo

// call this on a background thread!
private void requestGoogleAccountAccess() throws Exception
{
    googleAccountAccessGranted = GoogleAuthUtil.requestGoogleAccountsAccess(this);
    Log.i(TAG, "googleAccountAccessGranted: " + googleAccountAccessGranted);
}

// exception handler after calling method above
private void handleAuthResult(Throwable e)
{
    if (e instanceof UserRecoverableAuthException)
    {
        UserRecoverableAuthException authException = (UserRecoverableAuthException) e;
        startActivityForResult(authException.getIntent(), AUTH_PERMISSION_REQUEST);
    }
    else
    {
        Log.e(TAG, "Cannot request Google Account Access", e);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == AUTH_PERMISSION_REQUEST)
    {
        Log.i(TAG, "Google Auth Permission Result");

        if (resultCode == Activity.RESULT_CANCELED)
        {
            Log.w(TAG, "User Cancelled Play Services Auth Request.")
        }
        else if (resultCode == Activity.RESULT_OK)
        {
            Log.d(TAG, "User accepted Play Services Auth Request.");
            // call the following line again on a background thread. the call now returns a boolean instead of throwing an exception
            //  googleAccountAccessGranted = GoogleAuthUtil.requestGoogleAccountsAccess(this);
        }
    }
}

It's a bit strange why Google decided themselves for this "architecture". Why not return a Task, etc. But this is how you get it working.

Of course this code needs proper exception handling which I left out for readability.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!