所以我使用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。有人可以帮忙吗?