AccountManager挂在GetAuthToken()上

时间:2015-06-21 16:29:36

标签: java android multithreading android-asynctask oauth-2.0

所以我使用Android的AccountManager存储OAuth2凭据。然后,这些凭据将在getAuthToken方法中使用,就像任何其他客户经理一样。这是我的getAuthToken方法:

@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, final Account account, String authTokenType, Bundle options) throws NetworkErrorException {
    Log.d(TAG, "onGetAuthToken");
    final AccountManager am = AccountManager.get(context);

    String storeToken = am.peekAuthToken(account, authTokenType);

    final String password = am.getPassword(account);
    if (TextUtils.isEmpty(storeToken) && password != null) {
        storeToken = new OAuth2Client(account.name, password, "test", "test", Constants.getServerUrlBase() + "token.php").getAccessToken().getAccessToken();
    } else {
        if (password != null) {
            final Bundle result = new Bundle();
            String authToken = null;

            // Network stuff
            JSONObject JSONResult;
            DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
            HttpPost httppost = new HttpPost(Constants.SERVER_URL_BASE + "verify.php");
            List<NameValuePair> pairs = new ArrayList<>();
            pairs.add(new BasicNameValuePair("access_token", storeToken));
            try {
                httppost.setEntity(new UrlEncodedFormEntity(pairs));
            } catch (UnsupportedEncodingException e) {
                Log.e(TAG, "onFailed Posting\n" + e);
            }
            InputStream inputStream = null;

            try {
                HttpResponse httpResponse = httpClient.execute(httppost);
                HttpEntity entity = httpResponse.getEntity();

                inputStream = entity.getContent();
                // json is UTF-8 by default
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
                StringBuilder sb = new StringBuilder();

                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
                Log.d(TAG + "." + this.getClass().getEnclosingMethod(), "onReceivedData " + sb.toString());
                JSONResult = new JSONObject(sb.toString());


                if (JSONResult.getBoolean("success"))
                    authToken = storeToken;
            } catch (JSONException | IOException e) {
                Log.e(TAG, "onCrashed\n", e);
            } finally {
                if (inputStream != null) try {
                    inputStream.close();
                } catch (IOException e) {
                    Log.e(TAG, "Failed on inputStream!\n", e);
                }
            }
            if (authToken == null) {
                authToken = new OAuth2Client(account.name, password, "corentec_logistics_application", "corentec123", Constants.getServerUrlBase() + "token.php").getAccessToken().getAccessToken();
                am.invalidateAuthToken(Constants.ACCOUNT_TYPE, storeToken);
                am.setUserData(account, AccountManager.KEY_AUTHTOKEN, authToken);
            }

            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
            result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
            result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
            Log.d(TAG, "onPostExecute with String: " + authToken);
            return result;
        }
    }

    final Intent intent = new Intent(context, AuthenticatorActivity.class);
    intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
    intent.putExtra(AuthenticatorActivity.ARG_ACCOUNT_TYPE, account.type);
    intent.putExtra(AuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
    final Bundle bundle = new Bundle();
    bundle.putParcelable(AccountManager.KEY_INTENT, intent);
    return bundle;
}

基本上,这会获得用户凭据,如果令牌仍然有效或已过期,则检查服务器。如果令牌过期,它将从服务器获得一个新令牌并返回该令牌。如果令牌仍然很好,那么它只返回给定的令牌。根据被覆盖的类的要求,所有这一切显然都在捆绑中。这个方法我从我的应用程序类调用了一个更集中的方法。以下是应用程序类的重要部分:

public String getAuthToken() {
    String token = null;
    final String[] authToken = {null};

    GetToken getToken = new GetToken();
    getToken.execute();
    try {
        authToken[0] = getToken.get();
        return authToken[0];
    } catch (InterruptedException | ExecutionException e) {
        Log.e(TAG, "onCrashed\n", e);
    }
    return null;

}

而且......

private class GetToken extends AsyncTask<Void, Void, String> {
    String token = null;

    @Override
    protected String doInBackground(Void... params) {
        Log.d(TAG, "onDoInBackgroundExecute");
        try {

            token = accountManager.getAuthToken(getCurrentAccount(), Constants.TOKEN_TYPE, null, null, null, null).getResult().getString(AccountManager.KEY_AUTHTOKEN);
            Log.d(TAG, "Finished getting token: " + token);
        } catch (OperationCanceledException | IOException | AuthenticatorException e) {
            Log.e(TAG, "onCrashed getting token\n", e);
        }
        return token;
    }
}

然后我通过以下方式调用此活动:

application.setCurrentAccount(new Account(intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME), Constants.ACCOUNT_TYPE));
String token = application.getAuthToken();

application是Application类的实例。

但是,这会挂起活动。 Logcat和线程快照说这是由于这一行: token = accountManager.getAuthToken(getCurrentAccount(), Constants.TOKEN_TYPE, null, null, null, null).getResult().getString(AccountManager.KEY_AUTHTOKEN);

ASyncTask GetToken内部。我无法弄清楚为什么这是悬挂和去ANR。有人可以帮忙吗?

0 个答案:

没有答案