2

I'm using AccountManager to retrieve an account's auth token but the account manager hangs and the result is never returned. I originally tried to get it from the future directly but this always caused a hang. I switched to using an AccountManagerCallback but the callback never executes. What is weird is that a)I don't face this issue on any of the debug builds. Only on the release builds and b)only on Samsung and Moto G phones.

Here is my callback implementation

private class OnAccountManagerComplete implements AccountManagerCallback<Bundle> {

    private Account account;

    public OnAccountManagerComplete(Account account) {
        this.account = account;
    }

    @Override
    public void run(AccountManagerFuture<Bundle> future) {
        Bundle bundle;
        try {
            bundle = future.getResult();
            final String authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
            getDelegate().getConfiguration().setAccessToken(authToken);
            ((PregnancyActivityDelegate) getDelegate()).getRestService().activateProduct(account.name,
                    mActivateCallback);
        } catch (AuthenticatorException | OperationCanceledException | IOException e) {
            Log.e(OnAccountManagerComplete.class.getName(), e.getLocalizedMessage());
            e.printStackTrace();
            mProgressDialog.dismiss();
            Intent intent = new Intent(StartActivity.this, LoginActivity.class);
            intent.putExtra(LoginActivity.EXTRA_LOGIN_TYPE, LoginActivity.SIGN_IN);
            startActivity(intent);
        }
    }
}

And here is where I call getAuthToken

private void getExistingAuthToken(final Account account, String authTokenType) {
    mProgressDialog = ProgressDialog.show(StartActivity.this, "Retrieving Auth Token", "", true);
    Bundle options = new Bundle();
    mAccountManager.getAuthToken(account, authTokenType, options, this, new OnAccountManagerComplete(account), null);
}

Just to be thorough, here is my authenticator class. It's an abstract class because it resides in a shared library that is implemented by a couple of our apps

// region Public Static Constants
public static final String KEY_ACCOUNT_TYPE = "Ovia:AccountType";
public static final String KEY_AUTH_TYPE = "Ovia:AuthType";
public static final String KEY_NEW_ACCOUNT = "Ovia:IsNewAccount";

public static final String ACCOUNT_TYPE = "com.ovuline.ovia";
// endregion Public Static Constants

// region Private Members
private Context context;
// endregion Private Members

// region Constructors
public OviaAccountAuthenticator(Context context) {
    super(context);
    this.context = context;
}
// endregion Cosntructors

// region Parent Class Overrides
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
    return null;
}

@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
    final Intent authActivityIntent = getLoginIntent(context);
    authActivityIntent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
    authActivityIntent.putExtra(AccountManager.KEY_ACCOUNT_NAME, authTokenType);
    authActivityIntent.putExtra(KEY_NEW_ACCOUNT, true);
    authActivityIntent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);

    final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, authActivityIntent);
    return bundle;
}

@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
    return null;
}

@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
    final AccountManager accountManager = AccountManager.get(context);

    // Retrieve auth token from the account manager
    String authToken = accountManager.peekAuthToken(account, authTokenType);

    // If we found an auth token, return it in the bundle.  Else, launch the login activity
    // so a user can authenticate.
    if (!TextUtils.isEmpty(authToken)) {
        final Bundle authBundle = new Bundle();
        authBundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
        authBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
        authBundle.putString(AccountManager.KEY_AUTHTOKEN, authToken);
        return authBundle;
    }

    final Intent authIntent = getLoginIntent(context);
    authIntent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
    authIntent.putExtra(KEY_ACCOUNT_TYPE, account.type);
    authIntent.putExtra(KEY_AUTH_TYPE, authTokenType);
    final Bundle authBundle = new Bundle();
    authBundle.putParcelable(AccountManager.KEY_INTENT, authIntent);
    return authBundle;
}

@Override
public String getAuthTokenLabel(String authTokenType) {
    return authTokenType + " (label)";
}

@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
    return null;
}

@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
    final Bundle featuresBundle = new Bundle();
    featuresBundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
    return featuresBundle;
}
// endregion Parent Class Overrides

protected abstract Intent getLoginIntent(Context context);

Any insights you can give me with regards to this problem would be very useful.

Leeran7742
  • 21
  • 5

0 Answers0