I am pretty new to android developing and working with volley and got a few questions. I am trying to send a JSONArray via Post with volley and try to get back a String as response.
I have downloaded the volley files via github and got within the toolbox the JsonArrayRequest.java. This file contains a lot of information which I need for my task so I decided to mix it with the StringRequest.java and got out following:
New class called SendingJsonArray.java
package com.android.volley.toolbox;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.UnsupportedEncodingException;
/**
* A request for retrieving a {#link JSONArray} response body at a given URL.
*/
public class SendingJsonArray extends JsonRequest<JSONArray> {
/**
* Creates a new request.
* #param url URL to fetch the JSON from
* #param listener Listener to receive the JSON response
* #param errorListener Error listener, or null to ignore errors.
*/
public SendingJsonArray(String url, JSONArray JsonArry, Listener<JSONArray> listener, ErrorListener errorListener) {
super(Method.POST, url, JsonArry, listener, errorListener);
}
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
The first strange thing is that SendingJsonArray() doesn't contain a int method? It compiles and seems to work without it.
Than I changed the Method.GET to Method.POST. It compiles and seems to work again.
Than I added the "JSONArray JsonArry" within the SendingJsonArray and get following error:
error: no suitable constructor found for JsonRequest(int,String,JSONArray,Listener<JSONArray>,ErrorListener)
[javac] super(Method.POST, url, JsonArry, listener, errorListener);
[javac] ^
[javac] constructor JsonRequest.JsonRequest(int,String,String,Listener<JSONArray>,ErrorListener) is not applicable
[javac] (actual argument JSONArray cannot be converted to String by method invocation conversion)
[javac] constructor JsonRequest.JsonRequest(String,String,Listener<JSONArray>,ErrorListener) is not applicable
[javac] (actual and formal argument lists differ in length)
[javac] 1 error
OK I know what the problem is but I don t know how to solve this. Where is the original constructor and how can I modify mine that this will work?
If I get this working there will be the response listener left. I would try to copy the listener of StringRequest.java and hope that this will work?
#Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
Why are there two and what exactly are they created for? Sorry but the documentation about that isn't really helpful for me :/
Thanks for your help! :)
In order to send a JSONArray as param with volley library I implemented this class called JSONPostArrayRequest, which extends JSONRequest, maybe it can help you:
public class JsonPostArrayRequest extends JsonRequest<JSONObject> {
JSONArray params;
public JsonPostArrayRequest(String url, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener,JSONArray params) {
super(Method.POST, url, null, listener, errorListener);
this.params=params;
}
#Override
public byte[] getBody() {
if ( this.params != null && this.params.length() > 0) {
return encodeParameters( this.params, getParamsEncoding());
}
return null;
}
private byte[] encodeParameters(JSONArray params, String paramsEncoding) {
try {
return params.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
Related
I am trying to start an Intent based on the response code from the Server.
All the requests are carried out using Volley. Below is the Custom Request I'm using:
public class JSONObjectRequestUTF8 extends JsonObjectRequest {
public JSONObjectRequestUTF8(int method, String url, JSONObject jsonRequest,
Listener<JSONObject> listener, ErrorListener errorListener) {
super(method, url, jsonRequest, listener,
errorListener);
setShouldCache(false);
}
#Override
protected Response<JSONObject> parseNetworkResponse (NetworkResponse response) {
try {
String utf8String = new String(response.data, "UTF-8");
return Response.success(new JSONObject(utf8String), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
// log error
return Response.error(new ParseError(e));
} catch (JSONException e) {
// log error
return Response.error(new ParseError(e));
}
}
In ParseNetworkResponse the error code comes correctly. However I'm not able to work out how to start an Intent from here.
Any help would be appreciated.
Thank you very much in advance.
And have a nice day.
EDIT: Code for calling the above class
public class AuditAPI implements Response.Listener<JSONObject>, Response.ErrorListener {
private Context mContext;
private SharedPreferences deviceInfo;
public void makeAudit(final Context mContent,String ipAddress, int status){
this.mContext = mContent;
final HashMap<String, String> login_model = SessionManager.getInstance().getUserDetails(mContent);
JsonObjectRequest jsonObjReq = new JSONObjectRequestUTF8(Request.Method.POST, Constants.MAKE_AUDIT , null, this, this){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put(Constants.SUBJECTID,
login_model.get(Constants.SUBJECTID));
headers.put(Constants.ACCESSTOKEN,
login_model.get(Constants.ACCESSTOKEN));
headers.put("user-agent","Android");
headers.put("DEVICEID",Constants.DEVICE_ID);
headers.put("VAPPID", Constants.VAPP_ID);
headers.put("LOGIN_USER_NAME", (MyBaseActivity.getmUserId()));
headers.put("STATUS", String.valueOf(status));
headers.put("IPADDRESS",ipAddress);
headers.put("CONTENT_TYPE",Constants.JSON_FROMAT);
return headers;
}
};
jsonObjReq.setRetryPolicy(new DefaultRetryPolicy(1,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
MyApplicationController.getNewInstance(mContext).
addToRequestQueue(jsonObjReq, "AUDIT");
}
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.i("Failure", "onErrorResponse: ");
}
#Override
public void onResponse(JSONObject jsonObject) {
Log.i("Success","onResponse Audit");
}}
So I found a fix which was a tad tedious but simple.
Basically I had to override the deliverError method. In that method the errorCode was present, as a result based on that code I was able to perform the redirection.
Also needed to pass the context in the constructor. Needed to make that change in all request calls.
The reason this worked as per my understanding is that deliverError is called when the worker thread needs is trying to merge back to the main UI Thread. This bifurcation is caused in parseNetworkResponse since it's a heavy process which is why a worker thread is assigned to it.
Updated Class:
public class JSONObjectRequestUTF8 extends JsonObjectRequest {
//This is a new parameter
private Context context;
public JSONObjectRequestUTF8(int method, String url, JSONObject jsonRequest,
Listener<JSONObject> listener, ErrorListener errorListener,Context context) {
super(method, url, jsonRequest, listener,
errorListener);
this.context = context;
setShouldCache(false);
}
#Override
protected Response<JSONObject> parseNetworkResponse (NetworkResponse response) {
try {
String utf8String = new String(response.data, "UTF-8");
return Response.success(new JSONObject(utf8String), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
// log error
return Response.error(new ParseError(e));
} catch (JSONException e) {
// log error
return Response.error(new ParseError(e));
}
}
#Override
public void deliverError(VolleyError error) {
if(error.networkResponse.statusCode == HttpURLConnection.HTTP_PRECON_FAILED || error.networkResponse.statusCode == HttpURLConnection.HTTP_UNAUTHORIZED){
Intent i = new Intent(context, LoginActivity.class);
i.putExtra(EReceiptsConstants.ERROR_MESSAGE, EReceiptsConstants.SESSION_MESSAGE);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
return;
}
}
I need to send object value like
{
"Fromdate":"04/11/2018",
"Todate":"11/11/2018",
"Task":"abc"
}
I get response in array
[{}]
Please help for me
Thanks for advance.
If you could edit your question with a bit more explanation about your problem that would be great for me to help you. But I may know what you need.
Volley waits for a JsonRequest to be queued, but you can actually manage it the way you want, if the response from the server is an JsonArray and you want to send a JsonObject, you may want an approach as follows.
You have to extend JsonRequest and work over the response:
private class CustomJsonArrayRequest extends JsonRequest<JSONArray> {
public CustomJsonArrayRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONArray> listener, Response.ErrorListener errorListener) {
super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener);
}
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
Then you can setup your request:
JSONObject json = new JSONObject();
try {
json.put("Fromdate", "04/11/2018");
json.put("Todate", "11/11/2018");
json.put("Task", "abc");
} catch( JSONException e){
Log.e("ErrorBuildingJson", "Error building request JSONObject");
e.printStackTrace();
json = null; //GC this
}
//checkConnection is a custom method
if (json != null && checkConnection()) {
// Instantiate the RequestQueue
RequestQueue queue = Volley.newRequestQueue(this);
// Request a string response from the provided URL.
CustomJsonArrayRequest jsonRequest = new CustomJsonArrayRequest(Request.Method.POST, myURI, json,
new Response.Listener<JSONArray>(){
#Override
public void onResponse(JSONArray response) {
if (response != null && response.length() > 0) { //If the response is valid
// Do Stuff
} else { //If the response is not valid, the request also failed
Log.e("ErrorOnRequest", "The server responded correctly, but with an empty array!");
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("ErrorOnResponse", "Response from the server contains errors!");
}
}
);
// Add the request to the RequestQueue.
queue.add(jsonRequest);
}
Notice that this approach expects your server to wait for an simple json object and to return an json array as response.
This is a very common approach, and can be found in many repositories, since it gives you control over the request itself.
Sample: https://github.com/stefankorun/najdisme/blob/master/src/mk/korun/najdismestuvanje/net/CustomJsonArrayRequest.java
I hope this helps you.
I have a volley request with type GET , I want to pass it the number of page and numbers of posts in each page but it doesnt react to my parameter , here is my request :
(By the way , when I use getParams and getHeaders functions , it wont to anything too)
CustomRequest2 recListReq = new CustomRequest2(Constants.Posts +"?page="+count+"&per_page=1&categories=52" , new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Gson gson = new Gson();
...
and it is my CustomRequest :
public class CustomRequest2 extends JsonRequest<JSONArray> {
/**
* Creates a new request.
* #param url URL to fetch the JSON from
* #param listener Listener to receive the JSON response
* #param errorListener Error listener, or null to ignore errors.
*/
public CustomRequest2(String url, Listener<JSONArray> listener, ErrorListener errorListener) {
super(Request.Method.GET, url, null, listener, errorListener);
}
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
I face problem in encoding Arabic response from web , I am using volley to call web service
my tries to fix this issue.
I created custom request then parse network response with utf-8 encoding when I log to check result it give me strange writing here is my log {"data":null,"msg":"لا يوجد تنبيهات","status":false} and here is my full class , I made some tries as well according to previous answer fixEncodingUnicode but all tries failed .
I appreciate any help thanks
import android.text.Html;
import android.util.Log;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* Created by mina on 7/28/2016.
*/
public class myJsonObjectRequest extends JsonObjectRequest {
public myJsonObjectRequest(int method, String url, String requestBody, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, requestBody, listener, errorListener);
}
public myJsonObjectRequest(String url, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(url, listener, errorListener);
}
public myJsonObjectRequest(int method, String url, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, listener, errorListener);
}
public myJsonObjectRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, jsonRequest, listener, errorListener);
}
public myJsonObjectRequest(String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(url, jsonRequest, listener, errorListener);
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
response.headers.put("Content-Type",
response.headers.get("content-type"));
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
Log.v("network_response", jsonString + "encoding "+ response.headers.get("content-type"));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
private String DecodemyString(String msg) {
try {
return URLEncoder.encode(msg, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
public static String fixEncodingUnicode(String response) {
String str = "";
try {
str = new String(response.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String decodedStr = Html.fromHtml(str).toString();
return decodedStr;
}
}
finally I figure nice solution to all who face encoding issue
First : make sure your android studio encoding utf-8 ,
File -> Settings -> Editor -> File Encodings choose utf-8 in encoding project
reference
Second: here is the trick , we need to discover what encoding did we receive , we can approach that in parseNetworkResponse method by called response.headers.get("content-type").
in my case I got charset:utf-8 that mean encoding in utf-8 but in fact its not , how we discover real encoding type here is site detect encoding https://2cyr.com/decode/ , just past text in site and made site handle Select encoding : auto detect
it will return pasted text with all encoding scroll down to find write encoding (you will see your writing in original language )
get source encoding: , displayed as:
in my case I found source encoding : utf-8
displayed as: windows-1254
this why I create method fix encoding issue
public static String fixEncodingUnicode(String response) {
String str = "";
try {
// displayed as desired encoding
^ ^
| |
str = new String(response.getBytes("windows-1254"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String decodedStr = Html.fromHtml(str).toString();
return decodedStr;
}
I'm trying to use a custom Class that extend the JsonRequest class to send a JSONArrayRequest using POST and a parameter.
public class MethodJsonArrayRequest extends JsonRequest<JSONArray> {
public MethodJsonArrayRequest(int method, String url, JSONObject params, com.android.volley.Response.Listener<org.json.JSONArray> listener, ErrorListener errorListener) {
super(method, url, params.toString(), listener, errorListener);
Log.d("method", Integer.toString(method));
Log.d("jsonRequest", params.toString());
}
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
My logs return this:
D/method﹕ 1
D/jsonRequest﹕ {"idShow":"219"}
I'm passing this info to my custom class with this snippit:
...
JSONObject params = new JSONObject();
try {
params.put("idShow", idShow);
}
catch (JSONException e) {Log.d("JSON e", e.getMessage()); }
MethodJsonArrayRequest episodeRequest = new MethodJsonArrayRequest(Request.Method.POST, episodeURL, params, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray myResponse) {
try {
Log.d("myResponse", myResponse.toString());
...
Log of myResponse:
D/myResponse﹕ []
But for whatever reason it does not return anything, I feel like I might not be passing the right thing in for the paramas but I'm not sure, any help is greatly appreciated! Let me know if there is something I didn't include here that might be helpful.
user98239820 answer here was extreamly useful. Instead of extending JsonRequest<JSONArray> class he extended the Request class. I also had to change his new JSONObject to new JSONArray to fit my needs, but by pointing to that class works perfectly.