为什么 hasResolution() 和 getStatusCode==RESOLUTION_REQUIRED 在 SmartLock 中的行为不同?
Why do hasResolution() and getStatusCode==RESOLUTION_REQUIRED behave differently in SmartLock?
我们也有实施 Google Smart Lock 的应用程序。我们显然有相同的实现,但它们的行为不同。
第一个只会在用户已经保存了一些凭据时显示选择帐户的对话框,并且只显示他保存的一个或多个帐户。
第二个会始终显示一个对话框来选择帐户,即使用户从未保存过凭据,也会显示设备中的所有帐户。这会导致用户看到太多帐户,并且只选择一个自动完成没有密码的电子邮件。
我们花了一些时间才弄清楚发生了什么。碰巧我们正在检查不同条件下不成功的凭据请求的解决方案。第一个应用程序正在使用 result.getStatus().getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED
,而第二个应用程序正在使用 result.getStatus().hasResolution()
,即使状态代码不是 RESOLUTION_REQUIRED 而是 SIGN_IN_REQUIRED.
从命名上看,它们应该具有相似的行为,但它们没有。
为什么会有这种差异?
根据用户是否为调用应用程序存储凭据,CredentialsApi.request()
调用的结果状态代码会有所不同。查看 API overview 了解详细信息,但快速总结:
当用户有多个存储凭据(可能存储在设备上的一个或多个 Google 帐户中)时,将返回 RESOLUTION_REQUIRED
结果,并且可以通过显示多个已保存凭据的对话框来解决凭据,允许用户选择一个。 Details
当没有存储的凭据可用时,将返回 SIGN_IN_REQUIRED
结果,并且可以通过显示电子邮件地址列表的对话框来解决(对于电子邮件地址自动填充,以及名称或图片,如果可用) .这不需要设备权限(在 Android M 上非常有用,否则需要运行时 GET_ACCOUNTS 提示),并帮助用户轻松填写登录或注册表单。 Details
Auth.CredentialsApi.request(apiClient, request).setResultCallback(
new ResultCallback<CredentialRequestResult>() {
public void onResult(CredentialRequestResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
// Successfully read credential without any user interaction, this
// means there was only a single credential and user has auto
// sign-in enabled.
processRetrievedCredential(result.getCredential(), false);
} else if (status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED) {
// This is the case where the user has multiple saved
// credentials and needs to pick one
resolveResult(status, RC_READ);
} else if (status.getStatusCode() == CommonStatusCodes.SIGN_IN_REQUIRED) {
// User has no saved credentials, but a dialog to select email
// address (a "hint") is available (optional)
resolveResult(status, RC_HINT);
}
}
});
对于两个结果hasResolution()
returns true
,因为两者都可以解决,虽然结果不同,但不幸的是令人困惑。我们将更新文档以更好地解释。
在任何一种情况下,用户的选择都将在 onActivityResult()
中返回,但 "hints" 将仅设置标识符(电子邮件地址)而没有密码。
public void onActivityResult(int requestCode, int resultCode, Intent data) {
...
if (resultCode == RESULT_OK) {
Credential result = data.getParcelableExtra(Credential.EXTRA_KEY);
if (requestCode == RC_HINT) {
String email = result.getId(); // for auto-fill
} else if (requestCode == RC_READ) {
String email = result.getId(); // for auto sign-in
String password = result.getPassword(); // only for saved credentials
在 CredentialsApi.request()
中返回仅电子邮件对话框的原因是为了保存额外的 API 调用以获取上面详细描述的电子邮件 "hint" 选择器对话框,在否则应用程序需要按顺序进行 API 调用的情况。但是,这是可选的,因为对于许多应用程序的用户体验来说,在应用程序启动时检索凭据以进行自动登录更有意义,然后在用户开始登录或注册时单独请求电子邮件选择器对话框,如 [=22 所示=].
我们也有实施 Google Smart Lock 的应用程序。我们显然有相同的实现,但它们的行为不同。
第一个只会在用户已经保存了一些凭据时显示选择帐户的对话框,并且只显示他保存的一个或多个帐户。
第二个会始终显示一个对话框来选择帐户,即使用户从未保存过凭据,也会显示设备中的所有帐户。这会导致用户看到太多帐户,并且只选择一个自动完成没有密码的电子邮件。
我们花了一些时间才弄清楚发生了什么。碰巧我们正在检查不同条件下不成功的凭据请求的解决方案。第一个应用程序正在使用 result.getStatus().getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED
,而第二个应用程序正在使用 result.getStatus().hasResolution()
,即使状态代码不是 RESOLUTION_REQUIRED 而是 SIGN_IN_REQUIRED.
从命名上看,它们应该具有相似的行为,但它们没有。 为什么会有这种差异?
根据用户是否为调用应用程序存储凭据,CredentialsApi.request()
调用的结果状态代码会有所不同。查看 API overview 了解详细信息,但快速总结:
当用户有多个存储凭据(可能存储在设备上的一个或多个 Google 帐户中)时,将返回 RESOLUTION_REQUIRED
结果,并且可以通过显示多个已保存凭据的对话框来解决凭据,允许用户选择一个。 Details
当没有存储的凭据可用时,将返回 SIGN_IN_REQUIRED
结果,并且可以通过显示电子邮件地址列表的对话框来解决(对于电子邮件地址自动填充,以及名称或图片,如果可用) .这不需要设备权限(在 Android M 上非常有用,否则需要运行时 GET_ACCOUNTS 提示),并帮助用户轻松填写登录或注册表单。 Details
Auth.CredentialsApi.request(apiClient, request).setResultCallback(
new ResultCallback<CredentialRequestResult>() {
public void onResult(CredentialRequestResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
// Successfully read credential without any user interaction, this
// means there was only a single credential and user has auto
// sign-in enabled.
processRetrievedCredential(result.getCredential(), false);
} else if (status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED) {
// This is the case where the user has multiple saved
// credentials and needs to pick one
resolveResult(status, RC_READ);
} else if (status.getStatusCode() == CommonStatusCodes.SIGN_IN_REQUIRED) {
// User has no saved credentials, but a dialog to select email
// address (a "hint") is available (optional)
resolveResult(status, RC_HINT);
}
}
});
对于两个结果hasResolution()
returns true
,因为两者都可以解决,虽然结果不同,但不幸的是令人困惑。我们将更新文档以更好地解释。
在任何一种情况下,用户的选择都将在 onActivityResult()
中返回,但 "hints" 将仅设置标识符(电子邮件地址)而没有密码。
public void onActivityResult(int requestCode, int resultCode, Intent data) {
...
if (resultCode == RESULT_OK) {
Credential result = data.getParcelableExtra(Credential.EXTRA_KEY);
if (requestCode == RC_HINT) {
String email = result.getId(); // for auto-fill
} else if (requestCode == RC_READ) {
String email = result.getId(); // for auto sign-in
String password = result.getPassword(); // only for saved credentials
在 CredentialsApi.request()
中返回仅电子邮件对话框的原因是为了保存额外的 API 调用以获取上面详细描述的电子邮件 "hint" 选择器对话框,在否则应用程序需要按顺序进行 API 调用的情况。但是,这是可选的,因为对于许多应用程序的用户体验来说,在应用程序启动时检索凭据以进行自动登录更有意义,然后在用户开始登录或注册时单独请求电子邮件选择器对话框,如 [=22 所示=].