Android 8.0 Oreo - 账户
Android 8.0 Oreo - Accounts
在我的应用程序中,我需要知道是否有任何 Google 帐户或任何三星帐户。
最多 Android 7 可以通过以下方式轻松获取此信息:
Account[] accounts = AccountManager.get(getContext())
.getAccountsByType("com.google")
但是随着 Oreo
事件的发生,这不再有效了。
编辑:查看有关此主题的官方信息:
在 Android 8.0(API 级别 26)中,应用无法再访问用户帐户,除非验证器拥有帐户或用户授予该访问权限。 GET_ACCOUNTS 权限不再足够。要获得帐户访问权限,应用程序应使用 AccountManager.newChooseAccountIntent() 或特定于身份验证器的方法。获得帐户访问权限后,应用程序可以调用 AccountManager.getAccounts() 来访问它们。
Android 8.0 弃用 LOGIN_ACCOUNTS_CHANGED_ACTION。应用程序应该改为使用 addOnAccountsUpdatedListener() 在运行时获取有关帐户的更新。
有关为帐户访问和可发现性添加的新 API 和方法的信息,请参阅本文档新 API 部分中的帐户访问和可发现性
我花了半天时间找到了解决方案,但没有成功。
我发现信息声称现在访问帐户的唯一方法是像这样使用 AccountPicker
:
AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"},true, null, null, null, null);
但这确实解决了我的问题。明确地说,我只需要知道是否存在某种类型的帐户(Google,三星...)我不需要知道有多少,也不需要帐户信息。
如您所说,如果用户未授予您权限,则无法读取其他帐户。现在,该权限不仅通过 运行 时间权限提供,而且甚至通过帐户选择器提供,即只有当用户在您调用帐户选择器后 select 编辑了该帐户时,您的应用才能看到该帐户.这个新限制正是为了避免您尝试做的事情:读取所有用户帐户。您的问题没有解决方案,您唯一能做的就是将选择器呈现给用户并让他 select 所有帐户,但不是最好的用户体验。
编辑:从 Google Play Services 11.6 开始,现在有一种新方法 requestGoogleAccountsAccess()
可以获取所有 Google 个帐户。
使用 "android.permission.READ_CONTACTS" 许可,并且
Account[] accounts = AccountManager.get(getContext())
.getAccountsByType("com.google")
再次在 android Oreo
工作
使用此代码
在设备 运行 Oreo+ (8+) 上获取已安装的 google 帐户
Account[] accounts = AccountManager.get(getContext()).getAccountsByType("com.google")
您需要先致电
请先添加以下依赖
com.google.android.gms:play-services-auth:16.0.0
调用 requestGoogleAccountsAccess()
抛出一个异常,您可以将其(检查后)投射到 UserRecoverableAuthException
并从中获取以 startActivityForResult
开始的意图
这是一些示例代码,用于 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);
}
}
}
有点奇怪为什么Google自己决定了这个"architecture"。为什么不 return 任务等。
但这就是你让它工作的方式。
当然,这段代码需要适当的异常处理,为了便于阅读,我省略了这一点。
在我的应用程序中,我需要知道是否有任何 Google 帐户或任何三星帐户。
最多 Android 7 可以通过以下方式轻松获取此信息:
Account[] accounts = AccountManager.get(getContext())
.getAccountsByType("com.google")
但是随着 Oreo
事件的发生,这不再有效了。
编辑:查看有关此主题的官方信息: 在 Android 8.0(API 级别 26)中,应用无法再访问用户帐户,除非验证器拥有帐户或用户授予该访问权限。 GET_ACCOUNTS 权限不再足够。要获得帐户访问权限,应用程序应使用 AccountManager.newChooseAccountIntent() 或特定于身份验证器的方法。获得帐户访问权限后,应用程序可以调用 AccountManager.getAccounts() 来访问它们。 Android 8.0 弃用 LOGIN_ACCOUNTS_CHANGED_ACTION。应用程序应该改为使用 addOnAccountsUpdatedListener() 在运行时获取有关帐户的更新。 有关为帐户访问和可发现性添加的新 API 和方法的信息,请参阅本文档新 API 部分中的帐户访问和可发现性
我花了半天时间找到了解决方案,但没有成功。
我发现信息声称现在访问帐户的唯一方法是像这样使用 AccountPicker
:
AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"},true, null, null, null, null);
但这确实解决了我的问题。明确地说,我只需要知道是否存在某种类型的帐户(Google,三星...)我不需要知道有多少,也不需要帐户信息。
如您所说,如果用户未授予您权限,则无法读取其他帐户。现在,该权限不仅通过 运行 时间权限提供,而且甚至通过帐户选择器提供,即只有当用户在您调用帐户选择器后 select 编辑了该帐户时,您的应用才能看到该帐户.这个新限制正是为了避免您尝试做的事情:读取所有用户帐户。您的问题没有解决方案,您唯一能做的就是将选择器呈现给用户并让他 select 所有帐户,但不是最好的用户体验。
编辑:从 Google Play Services 11.6 开始,现在有一种新方法 requestGoogleAccountsAccess()
可以获取所有 Google 个帐户。
使用 "android.permission.READ_CONTACTS" 许可,并且
Account[] accounts = AccountManager.get(getContext())
.getAccountsByType("com.google")
再次在 android Oreo
工作使用此代码
在设备 运行 Oreo+ (8+) 上获取已安装的 google 帐户 Account[] accounts = AccountManager.get(getContext()).getAccountsByType("com.google")
您需要先致电
请先添加以下依赖
com.google.android.gms:play-services-auth:16.0.0
调用 requestGoogleAccountsAccess()
抛出一个异常,您可以将其(检查后)投射到 UserRecoverableAuthException
并从中获取以 startActivityForResult
这是一些示例代码,用于 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);
}
}
}
有点奇怪为什么Google自己决定了这个"architecture"。为什么不 return 任务等。 但这就是你让它工作的方式。
当然,这段代码需要适当的异常处理,为了便于阅读,我省略了这一点。