In my application, I'm using volley for networking. Now the backend team have made some changes in web-service call, which is before every api call I need to call one more service(oauth service) which will provide access token in it's JSON response. This access token is then used in my actual service(login service) call as a query in url. Means I need to make two calls, one after the other.
Implemented this change in my code i.e For eg say login service:
step 1) Call oauth service which gives access token.
step 2) Use this access token in url as a query for login service.
Now the problem is the calls are not in sync, I receive access token in response after login call thus getting an error
Login service call:
public void onClickLogin(View v) {
// Tag used to cancel the request
String tagJSONobj = "json_obj_req";
String url;
if(Constants.RUN_AUTH_API) {
authAuthentication = new AuthAuthentication(tinyDB, SignInActivity.this);
authAuthentication.getAuthToken();
url = https://abc.xyz.com/Services/api/UserValidation/userValidate.do?access_token= + tinyDB.getString(Constants.MY_SHARED_PREF_AUTH_TOKEN);
}else
{
url = Constants.SIGNIN_URL;
}
showDialog();
JSONObject object = new JSONObject();
try {
object.put("userName", name);
object.put("password", password);
object.put("appType", "MOB APP");
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST, url, object,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
hidePDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
System.out.print("error is" + error.getMessage());
error.printStackTrace();
Toast.makeText(SignInActivity.this, getResources().getString(R.string.login_service_error_message), Toast.LENGTH_SHORT).show();
}
}) ;
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq, tagJSONobj);
}
}
OAuth service call:
public class AuthAuthentication {
private static final String TAG = AuthAuthentication.class.getSimpleName();
private TinyDB tinyDB;
private Context context;
public AuthAuthentication(TinyDB tinyDB, Context context){
this.tinyDB = tinyDB;
this.context = context;
}
public void getAuthToken() {
String tag_json_obj = "json_obj_req";
String url = https://abc.xyz.com/Services/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=admin&password=admin";
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, "",
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Log.d(TAG, " Response" + response.toString());
tinyDB.putString(Constants.MY_SHARED_PREF_AUTH_TOKEN, "" + response.getString(AppTags.TAG_AUTH_TOKEN));
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
Toast.makeText(context, context.getResources().getString(R.string.unable_to_process), Toast.LENGTH_SHORT).show();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
}
}
Call OAuthsevice firstly on login button click and OnResponse method call login Api
OAuth service call:
public class AuthAuthentication {
private static final String TAG = AuthAuthentication.class.getSimpleName();
private TinyDB tinyDB;
private Context context;
public AuthAuthentication(TinyDB tinyDB, Context context){
this.tinyDB = tinyDB;
this.context = context;
}
public void getAuthToken() {
String tag_json_obj = "json_obj_req";
String url = https://abc.xyz.com/Services/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=admin&password=admin";
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, "",
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Log.d(TAG, " Response" + response.toString());
tinyDB.putString(Constants.MY_SHARED_PREF_AUTH_TOKEN, "" + response.getString(AppTags.TAG_AUTH_TOKEN));
onClickLogin();/// here to peform login
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
Toast.makeText(context, context.getResources().getString(R.string.unable_to_process), Toast.LENGTH_SHORT).show();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
}
UPDATE
if OAUTH will call multiple time we need is OAUTH key for diferent API...
Create This class in utility folder
public interface VolleyResponse {
void processFinish(String output);
}
just change you class constructor like this..
public class AuthAuthentication {
private static final String TAG = AuthAuthentication.class.getSimpleName();
private TinyDB tinyDB;
private Context context;
private VolleyResponse delegate;
public AuthAuthentication(TinyDB tinyDB, Context context,VolleyResponse delegate){
this.tinyDB = tinyDB;
this.context = context;
this.delegate= delegate;
}
--------
-------
}
In OnResponse method of AuthAuthentication class
#Override
public void onResponse(JSONObject response) {
try {
Log.d(TAG, " Response" + response.toString());
tinyDB.putString(Constants.MY_SHARED_PREF_AUTH_TOKEN, "" + response.getString(AppTags.TAG_AUTH_TOKEN));
//send response of volley
delegate.processFinish(tinyDB); //it will broadcast your response
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
and use this as you want. suppose you have to use in login click
login.setOnClickListerner(new View.OnClickListenr(){
#Override
public void onClick(View view){
AuthAuthentication auth= new AuthAuthentication(tinyDB,mContext,new VolleyResponse() {
#Override
public void processFinish(String output) {
//output conatins response
loginApicall();
}
}.getAuthToken(); ///if not work then auth.getAuthToken
}
});
Related
I want to get json response from local server. I want to add port in that. how to add port while using volley in android
In main activity
{
String url = "192.2.3.1:80/data";
sendAndRequestResponse(url, new VolleyCallback(){
#Override
public void onSuccess(JSONObject result){
}
});
}
private void sendAndRequestResponse(final String url, final VolleyCallback callback) {
//RequestQueue initialized
mRequestQueue = Volley.newRequestQueue(MainActivity.this, new ProxyPort());
//String Request initialized
mStringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(getApplicationContext(), "Response :" + response.toString(), Toast.LENGTH_LONG).show();//display the response on screen
Log.e("url", url);
Log.e("Response", response.toString());
try {
JSONObject obj = new JSONObject(response);
callback.onSuccess(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("ERR", "Error :" + error.toString());
}
});
VolleyLog.DEBUG = true;
mRequestQueue.add(mStringRequest);
}
I want to add port in this url. I want to access local host using ip. How to achieve it
I am trying to hit multiple request using Volley and i am getting response for all the request. my problem is how to identify the response is belong to which API.
mQueue = CustomVolleyRequest.getInstance(this.getApplicationContext())
.getRequestQueue();
final CustomJSONObjectrequest jsonRequest = new CustomJSONObjectrequest(Request.Method
.GET, url,
new JSONObject(), this, this); //
jsonRequest.setTag(REQUEST_TAG);
final CustomJSONObjectrequest jsonRequest2 = new CustomJSONObjectrequest(Request.Method
.GET, url2,
new JSONObject(), this, this);
jsonRequest2.setTag(REQUEST_TAG);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mQueue.add(jsonRequest);
mQueue.add(jsonRequest2); // Both the request will have different API request
}
});
}
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
#Override
public void onResponse(Object response) {
// How to identify, which response is belong to which api request
mTextView.setText("Response is: " + response);
}
Create a Generic Volley class and a Interface, Use the interface to get success and failure responds.
Step 1 Create a separate Volley class
Step 2 Create a interface for accessing the response from volley class
Step 3 create new object for
the class and send required parameters
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this(interfcae), "Submit", url, params);
Context of the class
Interface for sending Success and failure responds
Type of request to identify on success
url (mandatory)
Param (optional) for GET no need
Generic volley class
public class PostVolleyJsonRequest {
private String type;
private Activity act;
private VolleyJsonRespondsListener volleyJsonRespondsListener;
private String networkurl;
private JSONObject jsonObject = null;
private JSONObject params;
public PostVolleyJsonRequest(Activity act, VolleyJsonRespondsListener volleyJsonRespondsListener, String type, String netnetworkUrl,JSONObject params) {
this.act = act;
this.volleyJsonRespondsListener = volleyJsonRespondsListener;
this.type = type;
this.networkurl = netnetworkUrl;
this.params = params;
sendRequest();
}
private void sendRequest() {
Log.d("url", "url" + networkurl);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,networkurl,params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("response", "response " + response);
volleyJsonRespondsListener.onSuccessJson(response, type);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
NetworkResponse response = error.networkResponse;
Log.e("response", "response " + response);
if (response != null) {
int code = response.statusCode;
String errorMsg = new String(response.data);
Log.e("response", "response" + errorMsg);
try {
jsonObject = new JSONObject(errorMsg);
} catch (JSONException e) {
e.printStackTrace();
}
String msg = jsonObject.optString("message");
volleyJsonRespondsListener.onFailureJson(code, msg);
} else {
String errorMsg = error.getMessage();
volleyJsonRespondsListener.onFailureJson(0, errorMsg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
jsObjRequest.setRetryPolicy(new DefaultRetryPolicy(
600000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestqueue = Volley.newRequestQueue(act);
requestqueue.add(jsObjRequest);
}
}
Use the interface to get responds message
public interface VolleyJsonRespondsListener {
public void onSuccessJson(JSONObject result, String type);
public void onFailureJson(int responseCode, String responseMessage);
}
In your class where you want to include multiple request
public class TestVolley extends AppCompatActivity implements VolleyJsonRespondsListener{
//Your class code goes here
//network request
try {
//parameters
//Context,Interface,Type(to indentify your responds),URL,parameter for your request
//request 1
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "Submit", url, params);
//request 2
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "AccessData", url_2, params_2);
} catch (Exception e) {
e.printStackTrace()
}
//Methods from Interface
#Override
public void onSuccessJson(JSONObject result, String type) {
//Based on the Type you send get the responds and parse it
switch (type) {
case "Submit":
try {
parseSubmit(result);
} catch (Exception e) {
e.printStackTrace();
}
break;
case "AccessData":
try {
parseAccessData(result);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
You can do something like this for a single request. Same can be applied to the second request. This way you know which request is giving you the response.
final CustomJSONObjectrequest jsonRequest = new CustomJSONObjectrequest(Request.Method
.GET, url,
new JSONObject(), this, new Response.Listener<Object>() {
#Override
public void onResponse(Object response) {
// How to identify, which response is belong to which api request
mTextView.setText("Response is: " + response);
});
EDITED :
You can start with making an interface like :
public interface VolleyResponse {
void onResponse(JSONObject object, String tag);
void onError(VolleyError error, String tag);
}
Then you can make a custom handler for volley request like:
public class CustomJSONObjectRequest implements Response.Listener<JSONObject>, Response.ErrorListener {
private VolleyResponse volleyResponse;
private String tag;
private JsonObjectRequest jsonObjectRequest;
public CustomJSONObjectRequest(int method, String url, JSONObject jsonObject, String tag, VolleyResponse volleyResponse) {
this.volleyResponse = volleyResponse;
this.tag= tag;
jsonObjectRequest = new JsonObjectRequest(method, url, jsonObject, this, this);
}
#Override
public void onResponse(JSONObject response) {
volleyResponse.onResponse(response, tag);
}
#Override
public void onErrorResponse(VolleyError error) {
volleyResponse.onError(error, tag);
}
public JsonObjectRequest getJsonObjectRequest() {
return jsonObjectRequest;
}
}
And to call it in your class use it like:
CustomJSONObjectRequest request1 = new CustomJSONObjectRequest(Request.Method.GET, url,
new JSONObject(), "YOUR REQUEST TAG", this);
Make sure to let your class implement the VolleyResponse interface that will get you the response and your tag.
#Override
public void onResponse(JSONObject object, String tag) {
Log.i("Response :", object.toString() + " " + tag);
}
#Override
public void onError(VolleyError error, String tag) {
}
To add the request to the volley queue you can use:
mQueue.add(request1.getJsonObjectRequest());
PS : this code is not tested but it should work.
im pretty new to Android Studio and I'm trying to build a Get Request using Volley, the Server response is a JsonObject. I tested the code with breakpoints but I wonder why I don't jump into onResponse or why it won't work.
Here's my Code of the Get Method:
public Account GetJsonObject(String urlExtension, String name, Context context) {
String baseURL = "myurl.com/api";
baseURL += urlExtension + "/" + name;
// url will look like this: myurl.com/api/user/"username"
final Account user = new Account("","");
//Account(name, email)
RequestQueue requestQueue;
requestQueue = Volley.newRequestQueue(context);
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.GET, baseURL,null,
new Response.Listener<JSONObject>() {
// Takes the response from the JSON request
#Override
public void onResponse(JSONObject response) {
try {
JSONObject obj = response.getJSONObject("userObject");
String username = obj.getString("Username");
String email = obj.getString("Email");
user.setUsername(username);
user.setEmail(email);
}
catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonObject);
return user;
}
As #GVillavani82 commented your onErrorResponse() method body is empty. Try to log the error like this
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("ERROR", "Error occurred ", error);
}
}
Make sure that you have the below permission set in AndroidManifest.xml file and the api URL is proper.
<uses-permission android:name="android.permission.INTERNET"/>
And JsonObjectRequest class returns Asynchronous network call class. Modify your code like below.
// remove Account return type and use void
public void GetJsonObject(String urlExtension, String name, Context context) {
....
.... // other stuffs
....
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.GET, baseURL,null,
new Response.Listener<JSONObject>() {
// Takes the response from the JSON request
#Override
public void onResponse(JSONObject response) {
processResponse(response); // call to method
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("ERROR", "Error occurred ", error);
}
});
requestQueue.add(jsonObject);
}
Now create another method like below
private void processResponse(JSONObject response) {
try {
final Account user = new Account("","");
JSONObject obj = response.getJSONObject("userObject");
String username = obj.getString("Username");
String email = obj.getString("Email");
user.setUsername(username);
user.setEmail(email);
} catch (JSONException e) {
e.printStackTrace();
}
}
I want to save values from Response on user class variables.
Unfortunately, I cannot.
Help me please.
This is the code JSONObjectRequest
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
jsonURLFull, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(ActivityLogin.class.getSimpleName(), response.toString());
try {
User userClass = new User();
JSONObject jsonUser = response.getJSONObject("user");
userClass.id = jsonUser.getInt("id");
userClass.name = jsonUser.getString("email");
userClass.email = jsonUser.getString("email");
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Error: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
hidepDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(ActivityLogin.class.getSimpleName(), "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
hidepDialog();
}
});
AppController.getInstance().addToRequestQueue(jsonObjReq);
This is the User class:
public class User {
public int id;
public String name;
public String email;
}
This is the JSON of the API:
{"user":{"id":12,"name":"test_name","email":"test#email.com",}}
Two points for you :
1.you parse email to name attribude.
userClass.name = jsonUser.getString("name");
2.your json data is wrong due to the last ','
{"user":{"id":12,"name":"test_name","email":"test#email.com"}}
I have Authentication class which have method Auth with 2 arguments.
after calling that method a volley request generated and response catch through other function because of aSync. that object is a Static object and accessible in other class but that shows null always after making object or initializing it onCreate of activity.
Let check my Authenticate class:
public class Authenticate {
private static final String URL = "http://allskkc/zaigham/idsrs_authentication.php";
public static JSONObject finalresult;
public Authenticate() {
}
public static void Auth(String IEMI, String PIN) throws TimeoutException {
final JSONObject params = new JSONObject();
finalresult = new JSONObject();
RequestQueue queue = Volley.newRequestQueue(Splash.context);
try {
params.put("iemi", IEMI);
params.put("pin", PIN);
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("params to server", params.toString());
JsonObjectRequest jsOBJRequest = new JsonObjectRequest
(Request.Method.POST, URL, params, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("response from server", response.toString());
ftn(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Response error",error.toString());
}
});
queue.add(jsOBJRequest);
}
public static void ftn(JSONObject jsonObject) {
finalresult = jsonObject;
Log.e("as", "Response in ftn() = " + finalresult.toString());
}
}
final finalresult have value when I call that Auth() method but in my Login class it shows {}
let check my method call:
try {
Authenticate.Auth("358607051299527","1122");
} catch (TimeoutException e) {
e.printStackTrace();
}
Log.e("as","Prefrences Saved");
Log.e("as","My final result = "+Authenticate.finalresult.toString());
I attached my Log.e Image that may help more to understand.
You can see in your logs that application tries to get the result of request before request is done. Network request is asynchronous, it is done on background thread.
You should get the result after request is finished in some sort of callback.