Мой AsyncHttpClient
класс выглядит следующим образом.
ApiHttpClient.java
package virtualsystems.com.br.financial.client;
import android.content.Context;
import android.util.Log;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpRequestInterceptor;
import cz.msebera.android.httpclient.HttpResponseInterceptor;
import cz.msebera.android.httpclient.impl.client.DefaultHttpClient;
public class ApiHttpClient {
private static final String BASE_URL = "http://MY_IP_LOCAL_NETWORK/";
private static final Integer RETRY_COUNT = 2;
private static final Integer RETRY_DELAY = 500;
private static final Boolean URL_ENCODING = true;
private static AsyncHttpClient client = new AsyncHttpClient();
public ApiHttpClient() {
client.addHeader("Content-Type", "application/json");
client.addHeader("Accept", "application/json");
client.setUserAgent("Apache-HttpClient-AsyncHttpClient (Linux; Android 6.0) UNAVAILABLE (Java/0) Mobile");
client.setURLEncodingEnabled(URL_ENCODING);
client.setMaxRetriesAndTimeout(RETRY_COUNT, RETRY_DELAY);
}
private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
public static void get(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(context, getAbsoluteUrl(url), params, responseHandler);
}
public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.post(getAbsoluteUrl(url), params, responseHandler);
}
public static void delete(Context context, String url, Header[] headers, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.delete(context, getAbsoluteUrl(url), headers, params, responseHandler);
}
public static void put(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.put(context, getAbsoluteUrl(url), params, responseHandler);
}
public static void addResponseInterceptor(HttpResponseInterceptor interceptor) {
Log.d("ApiHttpClient", client.getHttpClient().getClass().getName());
Log.d("ApiHttpClient", "is DefaultHttpClient: " + (client.getHttpClient() instanceof DefaultHttpClient));
DefaultHttpClient defaultHttpClient = (DefaultHttpClient) client.getHttpClient();
defaultHttpClient.addResponseInterceptor(interceptor);
}
public static void addRequestInterceptor(HttpRequestInterceptor interceptor) {
Log.d("ApiHttpClient", client.getHttpClient().getClass().getName());
Log.d("ApiHttpClient", "is DefaultHttpClient: " + (client.getHttpClient() instanceof DefaultHttpClient));
DefaultHttpClient defaultHttpClient = (DefaultHttpClient) client.getHttpClient();
defaultHttpClient.addRequestInterceptor(interceptor);
}
}
В моей деятельности
MainActivity.java
package virtualsystems.com.br.financial;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.loopj.android.http.AsyncHttpResponseHandler;
import java.io.IOException;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpException;
import cz.msebera.android.httpclient.HttpRequest;
import cz.msebera.android.httpclient.HttpRequestInterceptor;
import cz.msebera.android.httpclient.client.HttpClient;
import cz.msebera.android.httpclient.impl.client.HttpClientBuilder;
import cz.msebera.android.httpclient.protocol.HttpContext;
import virtualsystems.com.br.financial.client.ApiHttpClient;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
ApiHttpClient apiHttpClient = new ApiHttpClient();
UserSession userSession = UserSession.getInstance(MainActivity.this);
@SuppressLint("CheckResult")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);UserSession userSession = UserSession.getInstance(getApplicationContext());
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View headerView = navigationView.getHeaderView(0);
TextView navUsername = (TextView) headerView.findViewById(R.id.nav_header_username);
TextView navEmail = (TextView) headerView.findViewById(R.id.nav_header_email);
ImageView navAvatar = (ImageView) headerView.findViewById(R.id.nav_header_avatar);
navUsername.setText(userSession.getUserName());
navEmail.setText(userSession.getUserEmail());
String imgURL = (String) userSession.getUserAvatar();
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.mipmap.ic_launcher_round);
requestOptions.error(R.mipmap.ic_launcher_round);
Glide.with(this)
.load(imgURL)
.apply(requestOptions)
.into(navAvatar);
displayFragment(R.id.nav_home);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
Toast.makeText(this, "Settings Clicked", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
displayFragment(id);
return true;
}
private void displayFragment(int itemId){
Fragment fragment = null;
switch (itemId){
case R.id.nav_categories:
fragment = new Categories();
break;
case R.id.nav_home:
fragment = new BillsTotal();
break;
case R.id.nav_bills:
fragment = new Bills();
break;
case R.id.nav_logout:
logoutUser();
break;
}
if (fragment != null){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
private void logoutUser() {
apiHttpClient.addRequestInterceptor(new HttpRequestInterceptor() {
@Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
request.addHeader("Authorization", "Bearer " + userSession.getUserToken());
}
});
apiHttpClient.post("api/logout", null, new AsyncHttpResponseHandler(){
String responseMessage = "";
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
responseMessage = "Disconected";
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
switch (statusCode){
case 400:
responseMessage = "Bad Request - Invalid Token";
break;
case 401:
responseMessage = "Unauthorized - Invalid Token";
break;
case 500:
responseMessage = "Could not Invalidate Token";
break;
default:
String errorCode = ((Integer) statusCode).toString();
String errorMsg = responseBody.toString();
responseMessage = "Error: " + errorCode + "\n" + errorMsg;
break;
}
}
@Override
public void onFinish() {
super.onFinish();
userSession.clearSession();
Toast.makeText(getApplicationContext(), responseMessage, Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
}
});
}
}
Когда токен истекает, API возвращает JSONObject , содержащий {"error": "token_expired"}
и ошибку 401 .
В методе logoutUser () я обрабатываю ошибки с помощью switch. В случае сбоя запроса ( onFailure ) из-за истечения срока действия токена и возврата ошибки 401 , как лучше всего отправить POST запрос на обновление токен, а затем повторно отправить запрос на выход, например.