Reputation: 1056
I am currently trying to handle a situation in a demo application I'm writing where I have an expired access token, and I need to use a refresh token to get a new access token. Now for background tasks like this, I'd normally use an AsyncTask like my app currently does for login (which works fine), but I'm not sure how to do this - if it can even be done (I'm sure it can, but I'm just not seeing it right now).
Below is my current flow - the call to get() blocks the UI thread, which isn't what I'm supposed to be doing here. Our access ticket class contains both the access token and refresh token.
public boolean isLoggedIn() {
if (isFreshAccessToken())
return true;
// If the access token is expired, we'll need to use the
// refresh token to get another one. Use a background task
// to do this.
String refreshToken = preferences.getString(REFRESH_TOKEN_KEY, null);
if (StringUtils.isNotBlank(refreshToken)) {
RefreshAccessTokenAsyncTask refreshLogin = new RefreshAccessTokenAsyncTask();
refreshLogin.execute(refreshToken);
try {
return refreshLogin.get();
} catch (Exception e) {
Log.d(TAG, "isLoggedIn() : Exception in async task. Returning false.");
return false;
}
} else
return false;
}
Here is what my AsyncTask implementation currently looks like. The refreshAccessTicket() method simply makes the REST call to get the AccessTicket response.
private class RefreshAccessTokenAsyncTask extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... params) {
String refreshToken = params[0];
try {
// Get a new access token using the refresh token
// in the background ...
AccessTicket accessTicket = refreshAccessTicket(refreshToken);
// ... and save the updated information to the shared
// preferences
saveAccessTicket(accessTicket);
return true;
} catch (Exception ex) {
// If the call for a new access token fails for any reason,
// return FALSE. We'll force the user to log in again to
// get a completely new access ticket.
return false;
}
}
@Override
protected void onPostExecute(Boolean isLoggedIn) {
super.onPostExecute(isLoggedIn);
Log.d(TAG, "RefreshAccessTokenAsyncTask.onPostExecute() : " +
"Returning isLoggedIn value of " + isLoggedIn);
}
}
What am I missing here? As I mentioned above, I want this process to be silent - if the access token has expired, I want to use the refresh token to automatically get a new access token without the user having to do anything or have the app jump out of the current flow (such as getting a friends list, etc.) - it will happen in the background. Should I be using something other than AsyncTask?
Upvotes: 4
Views: 1435
Reputation: 5498
AsyncTask should work fine, but you can't get the result like that. Try something like this instead.
private interface Callback {
void done(boolean result);
}
private class RefreshAccessTokenAsyncTask extends AsyncTask<String, Void, Boolean> {
private Callback cb;
private RefreshAccessTokenAsyncTask(Callback callback)
cb = callback;
}
@Override
protected Boolean doInBackground(String... params) {
String refreshToken = params[0];
try {
// Get a new access token using the refresh token
// in the background ...
AccessTicket accessTicket = refreshAccessTicket(refreshToken);
// ... and save the updated information to the shared
// preferences
saveAccessTicket(accessTicket);
return true;
} catch (Exception ex) {
// If the call for a new access token fails for any reason,
// return FALSE. We'll force the user to log in again to
// get a completely new access ticket.
return false;
}
}
@Override
protected void onPostExecute(Boolean isLoggedIn) {
super.onPostExecute(isLoggedIn);
Log.d(TAG, "RefreshAccessTokenAsyncTask.onPostExecute() : " +
"Returning isLoggedIn value of " + isLoggedIn);
cb.done(isLoggedIn);
}
}
Then use the AsyncTask like so:
public boolean isLoggedIn() {
if (isFreshAccessToken())
return true;
// If the access token is expired, we'll need to use the
// refresh token to get another one. Use a background task
// to do this.
String refreshToken = preferences.getString(REFRESH_TOKEN_KEY, null);
if (StringUtils.isNotBlank(refreshToken)) {
Callback callback = new Callback() {
public void done(boolean result){
// whatever you need to do here
}
}
RefreshAccessTokenAsyncTask refreshLogin = new RefreshAccessTokenAsyncTask(callback);
refreshLogin.execute(refreshToken);
} else
return false;
}
Upvotes: 1