Last active
November 17, 2017 11:29
-
-
Save pritishjoshi94/50eb795317f416b1b8e82e04b73ace19 to your computer and use it in GitHub Desktop.
A Singleton class for the networking in android
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add AppController to your manifest file in
Otherwise you will get a null context error