0

我有一个使用 AccountManager 和自定义 AccountAuthenticator 注册用户的应用程序。

我需要实现该Log Out功能。

当用户单击Log Out按钮时,他们的帐户被成功删除,但活动保持不变,用户不会被重定向到AccountAuthenticatorActivity,但如果我关闭应用程序并再次打开它,它将显示身份验证屏幕(即帐户实际上已被删除)。

我的问题:

我是否必须自己执行重定向(使用finish(); startActivity(...);)或 Authenticator 和 AccountManager 应该为我处理它(因为我认为如果它被声明为服务,它应该)?


也许我必须实现某种帐户删除侦听器?

无论如何,这是我删除帐户的方法MainActivity

    private void performLogout() {
        Account[] accounts = accountManager.getAccountsByType(AccountGeneral.ACCOUNT_TYPE);
        if (accounts.length != 0) {    
            accountManager.clearPassword(accounts[0]);
            accountManager.invalidateAuthToken(AccountGeneral.ACCOUNT_TYPE,
                    accountManager.getAuthToken(accounts[0], AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, true,
                            accountManagerFuture -> {
                                try {
                                    Log.d("invalidateAuthToken", accountManagerFuture.getResult().toString());
                                } catch (android.accounts.OperationCanceledException | AuthenticatorException | IOException e) {
                                    e.printStackTrace();
                                }
                            }, null).toString());

            if (Build.VERSION.SDK_INT < 23) { // use deprecated method
              accountManager.removeAccount(accounts[0], accountManagerFuture -> {
                  try {
                      if (accountManagerFuture.getResult()) {
                          Log.d("Deprecated ACCOUNT REMOVAL", "ACCOUNT  REMOVED");

                      }
                  } catch (android.accounts.OperationCanceledException | IOException | AuthenticatorException e) {
                      e.printStackTrace();
                  }
              }, null);
          } else {
              accountManager.removeAccount(accounts[0], this, accountManagerFuture -> {
                  try {
                      if (accountManagerFuture.getResult() != null) {
                          Log.d("ACCOUNT REMOVAL", "ACCOUNT REMOVED");
                      }
                  } catch (android.accounts.OperationCanceledException | AuthenticatorException | IOException e) {
                      e.printStackTrace();
                  }
              }, null);
          }
        }
    }

顺便说一句,当我单击时Log Out,我可以在日志中看到以下行:

D/invalidateAuthToken: Bundle[{intent=Intent { cat=[2] cmp=discounty.com/.activities.LoginActivity (has extras) }}]

所以看起来我的LoginActivity(AccountAuthenticatorActivity)实际上想要出现,但有些东西阻止它这样做。

在我的自定义AccountAuthenticator中,我实现了这个方法(以及其他几个负责帐户和令牌创建的方法):

@Override
public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {
    Bundle bundle = new Bundle();
    boolean allowed = true;
    bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, allowed);
    return bundle;
}

在我的清单中,我以以下方式声明了服务:

<service
    android:name=".authenticator.DiscountyAuthenticationService"
    android:process=":auth">
    <intent-filter>
        <action android:name="android.accounts.AccountAuthenticator" />
    </intent-filter>
    <meta-data android:name="android.accounts.AccountAuthenticator"
        android:resource="@xml/authenticator" />
</service>

那么,我是否必须手动重定向用户,或者我需要改进代码中的某些内容以使 AccountManager 为我处理重定向?

4

1 回答 1

3

当您删除帐户时,AccountManager 不会启动另一个帐户设置。如果你想要这种行为,你需要自己实现它。

但是,我不建议以这种方式实施它。如果您单击“注销”,您不会期望再次直接重定向到登录屏幕。

相反,我会用两个按钮显示一条成功消息,例如“已成功注销”,一个显示“关闭”并关闭应用程序,另一个显示“再次登录”之类的内容,将用户再次带到登录屏幕。恕我直言,这对用户更友好。

无论如何,回答您的问题:如果您想自动进入登录屏幕,我会看到以下选项:

  1. 只需在用户点击“注销”时启动帐户设置(使用AccountManager.addAccount(...) )(可以选择使用 AccountManager.removeAccountExplicitly( ... ) 删除帐户)。删除(您自己的应用程序的)帐户不太可能失败(尤其是如果您允许 return truein getAccountRemovalAllowed(...)),因此在大多数情况下,假设删除成功应该是安全的。您的身份验证器必须处理帐户已经存在的情况,因为用户可以随时启动帐户设置。

  2. 等待accountManagerFuture.getResult()并开始帐户设置,就像在#1中一样,只有当它返回成功时。

  3. 在您的活动中使用addOnAccountsUpdatedListener(...)注册一个OnAccountsUpdateListener,以检查帐户是否存在。请注意,有三个触发器会导致调用此侦听器:

    一个。已创建帐号,包括其他应用的帐号

    湾。帐号已被移除,包括其他应用的帐号

    C。帐户的密码已更新,还包括其他应用程序的帐户(恕我直言,此事件应该对身份验证者保密,绝对不应该广播)。

    但是,回调不会收到触发器是什么的任何信息。因此,您需要自己查明您的帐户是否已被删除。

另请注意,您的代码似乎accountManagerFuture.getResult()在主线程中调用,这不是一个好主意,因为它可能会阻塞。AccountManager.removeAccount(...)的文档明确表示这是不允许的。即使您在AccountManagerCallback回调中调用它并且您可能可以假设调用它是安全的,我也不会依赖它并确保它在后台线程中执行。如果您不让用户确认删除,您可能应该调用AccountManager.removeAccountExplicitly(...)

于 2015-12-30T15:31:58.613 回答