从 AccountManager 中删除帐户不会将用户发送到 AccountAuthenticatorActivity

Removing account from AccountManager doesn't send user to AccountAuthenticatorActivity

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

我需要实现 Log Out 功能。

当用户单击 Log Out 按钮时,他们的帐户被成功删除,但 activity 保持不变,用户不会被重定向到 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 为我处理重定向?

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

但是,我不建议以这种方式实施。如果您单击 "log out",您不会期望再次被直接重定向到登录屏幕。

相反,我会显示一条成功消息,如 "Logged out successfully",带有两个按钮,一个显示类似 "Close" 的内容并关闭应用程序,另一个显示类似 "login again" 的内容,它接受用户再次登录屏幕。这对用户更友好,恕我直言。

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

  1. 只需启动帐户设置(使用 AccountManager.addAccount(...)) when the user hits "logout" (optionally remove the account with AccountManager.removeAccountExplicitly(...))。删除(您自己的应用程序的)帐户不太可能失败(尤其是如果您允许 getAccountRemovalAllowed(...) 中的 return true),因此在大多数情况下,假设删除成功应该是安全的。您的身份验证器必须处理帐户已经存在的情况,因为用户可以随时启动帐户设置。

  2. 等待 accountManagerFuture.getResult() 并在 return 成功后像 #1 一样开始帐户设置。

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

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

    b。一个账号被删除,包括其他应用的账号

    c。更新了一个账号的密码,也包括其他应用的账号(恕我直言,这个事件应该是认证者私有的,绝对不应该广播)。

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

另请注意,您的代码似乎在主线程中调用 accountManagerFuture.getResult(),这不是一个好主意,因为它可能会阻塞。 AccountManager.removeAccount(...) explicitly says this is not allowed. Even if you're calling it in the AccountManagerCallback callback and you probably can assume that it's safe to call it I wouldn't rely on it and make sure it's executed in a background thread. If you don't let the user confirm the removal, you probably should call AccountManager.removeAccountExplicitly(...) 的文档代替。