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 (エクストラあり) }}]

私の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 は別のアカウント設定を開始しません。その動作が必要な場合は、自分で実装する必要があります。

ただし、そのように実装することはお勧めしません。「ログアウト」をクリックしても、ログイン画面に直接リダイレクトされることは期待できません。

代わりに、「ログアウトに成功しました」のような成功メッセージを 2 つのボタンで表示します。それはよりユーザーフレンドリーです、IMHO。

とにかく、あなたの質問に答えるために: ログイン画面に自動的に移動したい場合は、次のオプションが表示されます:

  1. ユーザーが「ログアウト」を押したときに( AccountManager.addAccount(...)を使用して) アカウントのセットアップを起動するだけです (オプションでAccountManager.removeAccountExplicitly(...)を使用してアカウントを削除します)。(自分のアプリの) アカウントの削除が失敗する可能性は低いため (特に で return を許可truegetAccountRemovalAllowed(...)ている場合)、ほとんどの場合、削除が成功したと想定しても問題ありません。ユーザーはいつでもアカウントのセットアップを開始できるため、Authenticator はアカウントが既に存在する場合に対処する必要があります。

  2. accountManagerFuture.getResult()#1 と同様に、成功が返された場合にのみ、アカウントのセットアップを待って開始します。

  3. アカウントが存在するかどうかを確認するアクティビティでaddOnAccountsUpdatedListener(...)を使用してOnAccountsUpdateListenerを登録します。このリスナーが呼び出される原因となる 3 つのトリガーがあることに注意してください。

    a. 他のアプリのアカウントを含め、アカウントが作成されました

    b. 他のアプリのアカウントを含め、アカウントが削除されました

    c. 他のアプリのアカウントも含めて、アカウントのパスワードが更新されました (私見では、このイベントはオーセンティケーターに対して非公開であり、絶対にブロードキャストされるべきではありません)。

    ただし、コールバックは、トリガーが何であったかについての情報を受け取りません。そのため、アカウントが削除されたかどうかを確認する必要があります。

accountManagerFuture.getResult()また、コードがメインスレッドで呼び出しているように見えることにも注意してください。これは、ブロックされる可能性があるため、お勧めできません。AccountManager.removeAccount(...)のドキュメントでは、これは許可されていないと明示的に述べています。コールバックで呼び出していて、それAccountManagerCallbackを呼び出しても安全であると想定できる場合でも、私はそれに依存せず、バックグラウンド スレッドで実行されるようにします。ユーザーに削除を確認させない場合は、代わりにAccountManager.removeAccountExplicitly(...)を呼び出す必要があります。

于 2015-12-30T15:31:58.613 に答える