I need a little help :)
I'm using volley on my Android app and I wrote this codes.
public String validateCredentials(final String email, final String password) {
StringRequest strReq = new StringRequest(com.android.volley.Request.Method.POST,
LOGIN_URL, new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject serverResponse = new JSONObject(response);
Log.d("Result: ", serverResponse.getString("result"));
responseServ = serverResponse.getString("result");
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put(email, password);
return params;
}
};
AppController.getInstance().addToRequestQueue(strReq);
return responseServ;
}
When I click the button Log.d("Result: ", serverResponse.getString("result")); this code is work but return responseServ; is not send any data on first click.
My button onClick code is
Toast.makeText(activity, authModel.validateCredentials(email, password), Toast.LENGTH_SHORT).show();
How do I solve this problem?
Thanks in advance
Volley is asynchronous aka you make the call, then later the callback is executed (Log.d() part). But you are also synchronously returning value which is empty the first time, and only the second time return values.
Have in mind that the second time it returns the first result.
What you have to do is do all your work in onResponse()
PS: As you want to keep MVP pattern you can- Define callback Interface and pass it to validateCredentials(final String email, final String password, final OnLoginComplete callback) and then in onResponse() callback.loginComplete()
Related
I want to send Array to server that looks like this :
"Array":["name"="something", "description"="something"]
To perform request i'm using this method :
private void saveNote(final int id, final String name, final String des, final String assing) {
Log.d(TAG, "Saving");
StringRequest stringRequest = new StringRequest(Request.Method.POST, Api.URL_CREATE_NOTE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("response", response.toString());
try {
JSONObject obj = new JSONObject(response);
if (!obj.getBoolean("error")) {
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> postParams = new HashMap<>();
Map<String, String> tableData= new HashMap<>();
tableDataParam.put("name",name);
tableDataParam.put("description",des);
postParams.put("Array[]", tableDataParam.toString());
return params;
}
};
VolleySingletonNotes.getInstance(context).addToRequestQueue(stringRequest);
}
First issue is that i can pass only String in postParams HashMap, so when i do tableData.toString the tableData have string brackets like this:
"Array":["{name=something, desciption=something}"]
And the second issue is that tableData HashMap for some reason dont put his String parameters in string brackets as you can see in example below first issue.
I already tried make JsonArray that fix the second issue but the first issue still remains, plus it automatically create backslashes(they dont show when i type them here)
Can anyone help me with this issue? Thanks.
I want to update the "Pass" field using WebAPI, I have created an HTTP PUT Request using Asp.Net WEB API and Android Java with Volley.
through Postman it's updating field value but when I test through my App it's updating the blank value in DB.
Thanks in advance.
private void callPUTDataMethod(String name, String job) {
loadingPB.setVisibility(View.VISIBLE);
String url = URL;
RequestQueue queue = Volley.newRequestQueue(PassUpdt.this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
loadingPB.setVisibility(View.GONE);
jobEdt.setText("");
userNameEdt.setText("");
// on below line we are displaying a toast message as data updated.
Toast.makeText(PassUpdt.this, "Data Updated..", Toast.LENGTH_SHORT).show();
try {
JSONObject jsonObject = new JSONObject("Pass");
String output = "Password Updated";
responseTV.setText(output);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(PassUpdt.this, "Fail to update data..", Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("EmpCd", "P010");
params.put("Pass", "12345");
params.put("Content-Type", "application/json; charset=utf-8");
return params;
}
};
queue.add(jsonObjectRequest);
}
}
I've setup a MySql server with a RESTful api to handle my login/signup system for my android app.
I'm creating an ASyncTask to handle the signup POST request, the server should return a JSON object telling us whether it was successful or not. When I input valid details and register on my Android app, the first response in onPostExecute is null. I press the button again and it is correct. What could I be doing wrong?
private class PostAndReadResponseTask extends AsyncTask<Account, Void, String> {
#Override
protected String doInBackground(Account... accounts) {
final Account thisAccount = accounts[0];
RequestQueue requestQueue = Volley.newRequestQueue(RegisterActivity.this);
final String signupURL = "http://localhost:8080/fitnessTrack/api.php?apicall=signup";
StringRequest stringRequest = new StringRequest(Request.Method.POST, signupURL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
responseJSON = response;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley Error:", error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("username", thisAccount.getUsername());
params.put("password", thisAccount.getPassword());
params.put("email", thisAccount.getEmail());
params.put("firstname", thisAccount.getFirstName());
return params;
}
};
requestQueue.add(stringRequest);
return responseJSON;
}
#Override
protected void onPostExecute(String result) {
System.out.println(result);
}
}
FYI: I edited the URL to say localhost, even though I'm using my own external IP. Even when the response is null, the database does update with the signup data.
The responseJSON is only updated here
#Override
public void onResponse(String response) {
responseJSON = response; // update UI using responseJSON in here
}
so it won't be ready until that method is called with the response. Try printing in there and it should work
I'm using Volley however I'm having some problems with the JSON parsed data most likely because volley doesn't implement something like AsyncTask's onPostExecute() and I'm getting some duplicated data on wrong list items.
Then I came across this: https://github.com/yakivmospan/volley-request-manager#custom-listener-implementation-
Has anyone use it? How can I add it to my current Volley code?
More details about my problem here Volley not sending correct data. How to implement an alternative to onPostExecute()?
UPDATE
As requested, some code. Here's a button that calls a method on another class that uses Volley to request some raw JSON data (NovaJSON) and then send the JSON to a parser class (NovaParser):
info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String instanceDetail = NovaJSON.shared().receiveDetail(getId());
Dialog dialog = new Dialog(v.getContext());
dialog.setContentView(R.layout.instances_info);
TextView image = (TextView) dialog.findViewById(R.id.imageInstance);
TextView flavor = (TextView) dialog.findViewById(R.id.flavorInstance);
dialog.setTitle(name.getText() + " Details");
if (instanceDetail != null) {
image.setText(" \u2022 image : " + NovaParser.shared().parseImages(instanceDetail));
flavor.setText(" \u2022 flavor : " + NovaParser.shared().parseFlavor(instanceDetail));
}
dialog.show();
}
});
This is the method that does the Volley request on the NovaJSON class:
public void getJSONdetail() {
final String authToken = getAuth();
String novaURL = getNova();
novaURL = novaURL+"/servers/"+id;
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, novaURL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("Nova on Response", response.toString());
setNovaJSONdetail(response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Nova on Error", "Error: " + error.getMessage());
setNovaJSONdetail(error.toString());
}
}
) {
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("X-Auth-Token", authToken);
params.put("User-Agent", "stackerz");
params.put("Accept", "application/json");
params.put("Content-Type", "application/json; charset=utf-8");
return params;
}
};
queue = VolleySingleton.getInstance(this).getRequestQueue();
queue.add(getRequest);
}
It then sends the JSON from the server as a string to be parsed using the following methods:
public static String parseImages(String imagesDetail){
ArrayList<HashMap<String, String>> imagesList = NovaParser.shared().getImagesList();
String temp = null;
JSONObject novaDetail = null;
try {
novaDetail = new JSONObject(imagesDetail);
JSONObject server = novaDetail.getJSONObject("server");
JSONObject image = server.getJSONObject("image");
if (imagesList !=null){
temp = image.getString("id");
for (Map<String,String> map : imagesList) {
if (map.containsValue(temp)) {
temp = map.get(NAME);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return temp;
}
public static String parseFlavor(String instanceDetail){
ArrayList<HashMap<String, String>> flavorList = NovaParser.shared().getFlavorList();
String temp = null;
JSONObject novaDetail = null;
try {
novaDetail = new JSONObject(instanceDetail);
JSONObject server = novaDetail.getJSONObject("server");
JSONObject flavor = server.getJSONObject("flavor");
if (flavorList !=null){
temp = flavor.getString("id");
for (Map<String,String> map : flavorList) {
if (map.containsValue(temp)) {
temp = map.get(NAME);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return temp;
}
When I press the button once the dialog is displayed with empty values. When I press it the second time I get the correct parsed data. Basically first time I click the button the instanceDetail string is null because Volley didn't finish doing its thing then I click the 2nd time it loads the values accordingly because it finally finished the 1st request.
I understand Volley is asynchronous, the requests happen in parallel and the responses sometimes are not immediate however I need some sort of progress bar or spinning wheel to give the user some feedback that the app is waiting for data. It could be done with AsyncTask however it doesn't seem to be possible with Volley.
I think your problem is not because of Volley.
Check the parameters you send and receive.
However if you need onPostExcecute you have Volley's callback:
Response.Listener<JSONObject> and Response.ErrorListener() which are called after the request.
About Volley request manager just switch all your volley calls with appropriate Volley request manager calls
I solved my problem by dumping Volley altogether and moving to Retrofit. I setup all the calls to be sync/blocking, worked out the exceptions/errors using try/catches and setup a short timeout on the OkHTTP client. Now it's working as I wanted.
I feel like this is a very basic concept missunderstanding. In my Android app I make HTTP requests using Volley lib. At first I made the requests through a JsonObjectRequest in the Activity code and worked right, but now I separated the request code in a class apart so I can call it from any Activity. The new class has a method that returns the requested JSONObject but any "json action" I do over the returned object ends in an error.
Here is the new class code, JSONRequests:
public class JSONRequests {
private JSONObject mResponse;
private String mURL = "https://myurl.com/";
public JSONObject getJSONObject(final String credentials, final String path) {
final JsonObjectRequest mRequest = new JsonObjectRequest(mURL.concat(path), null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
mResponse = response;
try {
Log.d("RESPONSE", mResponse.getString("id")); // It works here
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "Basic " + credentials);
return headers;
}
};
MyApplication.getInstance().getRequestQueue().add(mRequest);
return mResponse;
}
}
And here is how I call getJSONObject from MyActivity:
JSONRequests mRequest = new JSONRequests();
JSONObject mInfo = mRequest.getJSONObject(mEncodedCredentials, mPath);
try {
Log.d("RESPONSE", mInfo.getString("id")); // This doesn't work
} catch (JSONException e) {
e.printStackTrace();
}
When in the Activity file, I used "response" as a JSONObject and it worked, but now separated it won't. I don't know if is a error with JSONObject or just that I'm not getting the returned object in the correct way. Thanks in advance.