Volley attach access token to evey request using singleton
Asked Answered
J

3

6

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?

Junko answered 14/3, 2018 at 17:26 Comment(4)
You can use Request interceptor to capture the request and modify it before creating the actual requestBollard
Why don't you create a class, f.e. MyJsonObjectRequest, extending the JsonObjectRequest and override the class method getHeaders? Do you have any specific reason you want to do it in the singleton?Nahamas
@ZachariasHadjikyprianou its not a must that they are added in a sigleton but am looking for a way to prevent code duplication in multiple areasJunko
your singleton is not a singletonNearsighted
P
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); 
Perforate answered 27/3, 2018 at 5:43 Comment(1)
Shouldn't he override jsonObjectRequest ? Can jsonRequest be used for synchronous requests?Arlindaarline
N
0
  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).

Nearsighted answered 26/3, 2018 at 22:30 Comment(0)
S
-2

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);
        }
Shiekh answered 24/3, 2018 at 19:8 Comment(2)
where are the request headers added in your solution. Am looking for away to reduce code duplication when attaching the bearer request headerJunko
What you are doing now is creating AliSingleton class object again and again an calling method to attach request header. What I did is created a application level class in which therr is method to attach request header. You simply have to call method to attach request header and name that class in manifest as android:app tag.Shiekh

© 2022 - 2024 — McMap. All rights reserved.