Skip to content

Instantly share code, notes, and snippets.

@pritishjoshi94
Last active November 17, 2017 11:29
Show Gist options
  • Save pritishjoshi94/50eb795317f416b1b8e82e04b73ace19 to your computer and use it in GitHub Desktop.
Save pritishjoshi94/50eb795317f416b1b8e82e04b73ace19 to your computer and use it in GitHub Desktop.
A Singleton class for the networking in android
import android.content.Context;
import android.content.SharedPreferences;
/**
* @author Pritsh Joshi on 16-10-2017 10:17 PM.
* <p>
* This is for storing the user session and initialized whenever a user sign up or logs in
*/
@SuppressWarnings({"WeakerAccess", "unused"})
public class AuthPreferences
{
private static final String PREFERENCES_NAME = "auth";
private static final String TOKEN = "t";
private final SharedPreferences authSharedPreferences;
public AuthPreferences(Context context)
{
if (context == null)
{
throw new RuntimeException("Null Context is not excepted here.Check Your Application Clazz is added in the manifest or not");
}
authSharedPreferences = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
}
public UserAuth getUserAuthData()
{
String token = authSharedPreferences.getString(TOKEN, "");
if (!token.equals(""))
return new UserAuth(token);
else
return null;
}
public void setUserAuthData(UserAuth userAuth)
{
final SharedPreferences.Editor authEditor = authSharedPreferences.edit();
if (userAuth != null)
{
authEditor.putString(TOKEN, userAuth.getAuthToken());
authEditor.apply();
}
else
{
authEditor.clear();
authEditor.apply();
}
}
public final class UserAuth
{
private final String authToken;
public UserAuth(String authToken)
{
this.authToken = authToken;
}
public String getAuthToken()
{
return authToken;
}
}
}
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.net.ConnectivityManager;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Pritsh Joshi on 12-10-2017 05:08 PM.
* Add Volley Dependency to build(app).gradle file compile 'com.android.volley:volley:1.0.0'
* Add GSON Dependency to build(app).gradle file compile 'com.google.code.gson:gson:2.8.2'
* Add Uses permission <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> in manifest file
*/
@SuppressWarnings({"unused", "SameParameterValue", "WeakerAccess", "StatementWithEmptyBody"})
public class GsonNetworkRequest
{
private static final int TIME_OUT_TIME = 10000; // in milliseconds.
private static final int MAX_TRIES = 1; // No Of retries to a single request.
private static final String BASE_URL = U_BASE; // your project base url.
private static final Gson gson = new Gson(); // Json Serializer-Deserializer.
private final Context context = MyApplicationController.getInstance();
private final boolean isDebuggable = (0 != (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE));
private final String callerClassName;
private GsonNetworkListener gsonNetworkListener; // need help on this is this can be static for project.
private Map<String, String> requestParams = null; // Get-Post request url parameters.
public GsonNetworkRequest()
{
if (isDebuggable)
callerClassName = new Exception().getStackTrace()[1].getClassName();
else
callerClassName = "Caller";
}
private static String getCallerClassName()
{
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
for (int i = 1; i < stElements.length; i++)
{
StackTraceElement ste = stElements[i];
if (!ste.getClassName().equals(Debug.class.getName()) && ste.getClassName().indexOf("java.lang.Thread") != 0)
{
return ste.getFileName().split("\\.")[0];
}
}
return "";
}
public void doNetworkCalling(final int requestMethod, final String urlEndPoints, Type responseClassType)
{
if (isNetworkAvailable())
{
hasWhiteSpaces();
final String requestUrl = getUrl(requestMethod, urlEndPoints);
customNetworkRequest(requestMethod, requestUrl, urlEndPoints, null, responseClassType);
}
else
{
noInternetConnectionFound(urlEndPoints);
}
}
public void doNetworkCalling(final int requestMethod, final Object requestObject, final String urlEndPoints, Type responseClassType)
{
if (isNetworkAvailable())
{
hasWhiteSpaces();
final String requestUrl = getUrl(requestMethod, urlEndPoints);
final Object object = getRequestBody(requestObject, responseClassType);
customNetworkRequest(requestMethod, requestUrl, urlEndPoints, object.toString(), responseClassType);
}
else
{
noInternetConnectionFound(urlEndPoints);
}
}
private void hasWhiteSpaces()
{
if (getRequestParams() != null)
{
Pattern pattern = Pattern.compile("\\s");
for (Map.Entry<String, String> entry : requestParams.entrySet())
{
Matcher matcher = pattern.matcher(entry.getKey());
if (matcher.find())
{
throw new RuntimeException("Request Parameters should not contain white spaces in the key name.");
}
}
}
}
private Map<String, String> getRequestParams()
{
return requestParams;
}
public void setRequestParams(Map<String, String> requestParams)
{
this.requestParams = requestParams;
}
private String getUrl(int requestMethod, String urlEndPoints)
{
try
{
if (urlEndPoints.startsWith("http"))
{
return urlEndPoints;
}
else
{
StringBuilder requestUrl = new StringBuilder(BASE_URL + urlEndPoints);
if ((requestMethod == Request.Method.GET) && (requestParams != null) && (requestParams.size() != 0))
{
Map<String, String> urlParameters = getRequestParams();
setRequestParams(null);
requestUrl.append("?");
for (Map.Entry<String, String> entry : urlParameters.entrySet())
{
requestUrl.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "utf-8")).append("&");
}
return requestUrl.substring(0, requestUrl.length() - 1);
}
else
{
return requestUrl.toString();
}
}
} catch (final UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
private Object getRequestBody(Object requestObject, Type responseClassType)
{
try
{
JSONObject jsonObject;
if (requestObject == null)
{
throw new RuntimeException("Request body is null,Correct this or try to use get method instead.");
}
else if (requestObject instanceof JSONObject)
{
jsonObject = (JSONObject) requestObject;
return jsonObject;
}
else if (requestObject instanceof String)
{
return requestObject;
}
else
{
jsonObject = new JSONObject(gson.toJson(requestObject, requestObject.getClass()));
return jsonObject;
}
} catch (JSONException e)
{
throw new RuntimeException(e);
}
}
private boolean isNetworkAvailable()
{
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert cm != null;
return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
private void noInternetConnectionFound(String requestEndPoints)
{
gsonNetworkListener.onResponseReceived(new ResponseError(404, getResourceString("no_internet_connection"), requestEndPoints, "no_internet"), requestEndPoints, null);
}
public void setGsonNetworkListener(GsonNetworkListener gsonNetworkListener)
{
this.gsonNetworkListener = gsonNetworkListener;
}
private String getResourceString(String string)
{
String packageName = context.getPackageName();
int resId = context.getResources().getIdentifier(string, "string", packageName);
if (resId == 0)
{
throw new RuntimeException(string + " resource string not exists in your application.");
}
return context.getResources().getString(resId);
}
private void customNetworkRequest(final int requestMethod, final String finalUrl, final String urlEndpoints, final String requestBody, final Type responseClassType)
{
// MyApplicationController.getInstance().getReqQueue().getCache().clear();
StringRequest stringRequest = new StringRequest(requestMethod, finalUrl, new Response.Listener<String>()
{
@Override
public void onResponse(String response)
{
if (gsonNetworkListener == null)
{
throw new RuntimeException("Request Listener is null From the " + callerClassName + " class.");
}
else
{
if (response.isEmpty())
{
gsonNetworkListener.onResponseReceived(new ResponseError(500, getResourceString("no_response_from_server"), urlEndpoints, "blank_data"), urlEndpoints, null);
}
else if (responseClassType == String.class)
{
gsonNetworkListener.onResponseReceived(response, urlEndpoints, null);
}
else if (responseClassType == JSONObject.class)
{
try
{
gsonNetworkListener.onResponseReceived(new JSONObject(response), urlEndpoints, null);
} catch (JSONException e)
{
throw new RuntimeException(e);
}
}
else
{
Log.e("object", response);
Log.e("url", finalUrl);
gsonNetworkListener.onResponseReceived(gson.fromJson(response, responseClassType), urlEndpoints, null);
}
}
}
}, new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error)
{
if (gsonNetworkListener == null)
{
throw new RuntimeException("Request Listener is null From the " + callerClassName + " class.");
}
else if (error.networkResponse != null && error.networkResponse.data != null)
{
final int statusCode = error.networkResponse.statusCode;
try
{
String errorResponse = new String(error.networkResponse.data, "utf-8");
if (statusCode == 500)
{
gsonNetworkListener.onResponseReceived(new ResponseError(500, getResourceString("something_wrong_server"), urlEndpoints, "server_internal_error"), urlEndpoints, error);
if (isDebuggable)
{
android.util.Log.e("SeverError", new String(errorResponse.getBytes(), "utf-8"));
}
}
else if (statusCode == 401)
{
// TODO change later
MyApplicationController.getAuthPreferences().setUserAuthData(null);
MyApplicationController.getInstance().startActivity(new Intent(MyApplicationController.getInstance(), MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
}
else
{
gsonNetworkListener.onResponseReceived(gson.fromJson(errorResponse, ResponseError.class), urlEndpoints, error);
}
} catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
else
{
gsonNetworkListener.onResponseReceived(new ResponseError(404, getResourceString("something_wrong_server_client"), urlEndpoints, "not_detected"), urlEndpoints, error);
}
}
})
{
@Override
public String getBodyContentType()
{
return "application/json; charset=utf-8";
}
@Override
public byte[] getBody() throws AuthFailureError
{
try
{
if (requestMethod == Method.GET)
{
return null;
}
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException e)
{
return null;
}
}
@Override
protected Map<String, String> getParams() throws AuthFailureError
{
if (getRequestParams() != null)
{
Map<String, String> params = getRequestParams();
setRequestParams(null);
return params;
}
return super.getParams();
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError
{
if (MyApplicationController.getAuthPreferences().getUserAuthData() != null)
{
// TODO check here for your headers
Map<String, String> headers = new HashMap<>();
headers.put("Auth", MyApplicationController.getAuthPreferences().getUserAuthData().userAuthToken);
return headers;
}
else
{
return super.getHeaders();
}
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(TIME_OUT_TIME, MAX_TRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
stringRequest.setTag(urlEndpoints);
// stringRequest.setShouldCache(false);
MyApplicationController.getInstance().getReqQueue().add(stringRequest);
}
public void cancelRequest(String urlToCancel)
{
if (MyApplicationController.getInstance().getReqQueue() != null)
{
if (urlToCancel != null)
{
MyApplicationController.getInstance().getReqQueue().cancelAll(urlToCancel);
}
}
}
public interface GsonNetworkListener
{
void onResponseReceived(Object response, String requestEndpoint, VolleyError volleyError);
}
public class ResponseError
{
@SerializedName("status_code")
private int responseCode;
@SerializedName("message")
private String responseMessage;
@SerializedName("url_endpoint")
private String responseEndpoint;
@SerializedName("error")
private String responseError;
public ResponseError(int responseCode, String responseMessage, String responseEndpoint, String responseError)
{
this.responseCode = responseCode;
this.responseMessage = responseMessage;
this.responseEndpoint = responseEndpoint;
this.responseError = responseError;
}
public int getResponseCode()
{
return responseCode;
}
public String getResponseMessage()
{
return responseMessage;
}
public String getResponseEndpoint()
{
return responseEndpoint;
}
public String getResponseError()
{
return responseError;
}
}
}
/*
<string name="no_internet_connection">No Internet Connection.</string>
<string name="no_response_from_server">No response from server.</string>
<string name="something_wrong_server">Something went wrong on server.</string>
<string name="something_wrong_server_client">Something wrong either client or server side.</string>
*/
import android.annotation.SuppressLint;
import android.app.Application;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
/**
* @author Pritsh Joshi on 14-10-2017 01:16 PM.
*/
public class MyApplicationController extends Application
{
@SuppressLint("StaticFieldLeak")
private static MyApplicationController sInstance;
private static AuthPreferences authPreferences;
private RequestQueue mRequestQueue;
public static AuthPreferences getAuthPreferences()
{
return authPreferences;
}
public static synchronized MyApplicationController getInstance()
{
return sInstance;
}
@Override
public void onCreate()
{
super.onCreate();
sInstance = this;
authPreferences = new AuthPreferences(MyApplicationController.this);
}
public RequestQueue getReqQueue()
{
if (mRequestQueue == null)
{
mRequestQueue = Volley.newRequestQueue(MyApplicationController.this);
}
return mRequestQueue;
}
}
@pritishjoshi94
Copy link
Author

pritishjoshi94 commented Oct 8, 2017

Add AppController to your manifest file in

Otherwise you will get a null context error

<application
android:name=".AppController"
...
>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment