Wednesday, March 28, 2018

Volley attach access token to evey request using singleton

Leave a Comment

I am doing the following which perfectly works

    //else proceed with the checks     JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(             Request.Method.GET,             checkauthurl,             null,             new Response.Listener<JSONObject>() {                 @Override                 public void onResponse(String response) {                           //do stuff here                 }             },             new Response.ErrorListener() {                 @Override                 public void onErrorResponse(VolleyError error) {                    // do stuff here                 }             }) {                 @Override                 public Map<String, String> getHeaders() throws AuthFailureError {                     HashMap<String, String> headers = new HashMap<String, String> ();                     TokenService tokenservice = new TokenService(ctx);                     String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);                     headers.put("Authorization", "Bearer " + accesstoken);                      return headers;               }     };      // Access the RequestQueue through your singleton class.     ApiSingleton strngle = new ApiSingleton(ctx);     strngle.addToRequestQueue(jsonObjectRequest); 

For every request, I have to add the request header. How can I set request headers directly in the singleton.

This is my singleton

private static ApiSingleton mInstance; private RequestQueue mRequestQueue; public static Context mCtx; private ImageLoader mImageLoader;  public ApiSingleton(Context context) {     mCtx = context;     mRequestQueue = getRequestQueue();     //do stuff }  public RequestQueue getRequestQueue() {     if (mRequestQueue == null) {         // getApplicationContext() is key, it keeps you from leaking the         // Activity or BroadcastReceiver if someone passes one in.         mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());     }     return mRequestQueue; } 

How do I avoid the above code duplication when attaching the bearer token in every request?

3 Answers

Answers 1

public class CustomJsonRequest extends JsonRequest<Object>{     public CustomJsonRequest(String url, String requestBody, Response.Listener<Object> listener,                        Response.ErrorListener errorListener) {         super(url, requestBody, listener, errorListener);     }      public CustomJsonRequest(int method, String url, String requestBody, Response.Listener<Object> listener,                        Response.ErrorListener errorListener) {         super(method, url, errorListener);     }     @Override     protected Response<Object> parseNetworkResponse(NetworkResponse response) {         return Response.success(Object, HttpHeaderParser.parseCacheHeaders(response));     }      @Override     public Map<String, String> getHeaders() throws AuthFailureError {         Map<String, String> headers = new HashMap<String, String> ();         TokenService tokenservice = new TokenService(ctx);         String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);         headers.put("Authorization", "Bearer " + accesstoken);         return headers;     } } 

You can extend JsonRequest class and override getHeaders() method. Pass instance of CustomJsonRequest object when you are adding volley requests in queue.

VolleyUtils.getInstance().addToRequestQueue(customJsonRequest);  

Answers 2

  1. You can write a "Factory" with a method that takes your checkauthurl and ctx and returns you an instance of the JsonObjectRequest. Your factory could implement some logic for re-use of objects that have the same auth Url if that makes sense in your case.
  2. You can sub-class JsonObjectRequest and provide your checkauthurl and ctx as a parameter to the constructor. Similarly, you can implement a scheme to re-use the objects

The factory would be the suggested approach if you want Dependency Injection.

I would recommend against pre-allocating the Token and using it in multiple requests. Tokens expire. If the TokenService is written well, it should know when tokens will expire and refresh as needed (if possible).

Answers 3

Make an AppController.java file and mention this file name as android:app in manifest tag.

public class AppController extends Application {      public static final String TAG = AppController.class.getSimpleName();     private RequestQueue mRequestQueue;     private static AppController mInstance;     private ImageLoader mImageLoader;      @Override     public void onCreate() {         super.onCreate();         mInstance = this;     }     public static synchronized AppController getInstance() {         return mInstance;     }      public RequestQueue getRequestQueue() {         if (mRequestQueue == null) {             mRequestQueue = Volley.newRequestQueue(getApplicationContext());         }         return mRequestQueue;     }      public ImageLoader getImageLoader() {         getRequestQueue();         if (mImageLoader == null) {             mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache());         }         return this.mImageLoader;     }     public <T> void addToRequestQueue(Request<T> req, String tag) {         req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);         getRequestQueue().add(req);     }     public <T> void addToRequestQueue(Request<T> req) {         req.setTag(TAG);         getRequestQueue().add(req);     }     public void cancelPendingRequests(Object tag) {         if (mRequestQueue != null) {             mRequestQueue.cancelAll(tag);         }     } } 

Do the networking code

 StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_BUYER_LOGIN,  new Response.Listener<String>() {                  @Override                 public void onResponse(String response) {                  }             }, new Response.ErrorListener() {                  @Override                 public void onErrorResponse(VolleyError error) {                  }             }) {                 @Override                 protected Map<String, String> getParams() {                  }             };             // Adding request to request queue             AppController.getInstance().addToRequestQueue(strReq, tag_string_req);         } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment