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

时间:2015-12-30 13:34:26

标签: android authentication android-service accountmanager android-authenticator

我有一个使用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(有额外内容)}}]

所以似乎我的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为我处理重定向?

1 个答案:

答案 0 :(得分:3)

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

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

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

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

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

  2. 等待accountManagerFuture.getResult()并启动帐户设置,就像在#1中返回成功一样。

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

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

    湾帐户已被删除,包括其他应用的帐户

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

    但是,回调函数不会收到触发器的任何信息。因此,如果您的帐户已被删除,您需要了解自己。

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