I am making http requests to my REST server. As a response I get the JSON body. But I need to get also a parameter from the response header, as I keep the user token in it. I have looked at a lot of posts on Stack Overflow for similar questions, but I they don't seem to have helped me. I want to make a JSON request, and get the body and headers form the response. How can I do it? Here is my code:
Please don't mark the question as duplicate, as I have not found any example where I can retrieve both: the response header and the response body. For the existing questions, users get only the headers
JsonObjectRequest req = new JsonObjectRequest(AppConfig.URL_LOGIN, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response.toString());
hideDialog();
try {
JSONObject jObj = response;
String uid = jObj.getString("_id");
String name = jObj.getString("fullName");
String email = jObj.getString("email");
// Inserting row in users table
db.addUser(name, email, uid);
Toast.makeText(getApplicationContext(), "User successfully registered. Try login now!", Toast.LENGTH_LONG).show();
Intent intent = new Intent(
LoginActivity.this,
MainActivity.class);
startActivity(intent);
finish();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
String toastError = "Response code: " + networkResponse.statusCode;
Toast.makeText(getApplicationContext(),
toastError, Toast.LENGTH_LONG).show();
hideDialog();
}
});
You can't do that using JsonObjectRequest. You should extend the Request class and implement parseNetworkResponse() method which provides access to low-level NetworkResponse object. Downside is of course that you have to re-implement JSON parsing as well, but this is not really a big deal.
Something like:
public class HeaderAwareJsonRequest extends Request<Pair<JSONObject,Map>> {
protected Response.Listener<Pair<JSONObject,Map>> listener;
public HeaderAwareJsonRequest( int method, String url, Response.Listener<Pair<JSONObject,Map>> listener, Response.ErrorListener errorListener ) {
super( method, url, errorListener );
this.listener = listener;
}
#Override
protected Response<Pair<JSONObject,Map>> parseNetworkResponse( NetworkResponse response ) {
try{
String jsonString = new String( response.data, HttpHeaderParser.parseCharset( response.headers ) );
// pair contains the json body and headers
Pair pair = new Pair( new JSONObject( jsonString ), response.headers );
return Response.success( pair, HttpHeaderParser.parseCacheHeaders( response ) );
}catch( Exception e ){
return Response.error( new ParseError( e ) );
}
}
}
then in the calling code:
HeaderAwareJsonRequest req = new HeaderAwareJsonRequest(
Request.Method.GET,
AppConfig.URL_LOGIN,
new Response.Listener<Pair<JSONObject,Map>>() {
#Override
public void onResponse(Pair<JSONObject,Map> response) {
JSONObject jObj = response.first;
Map headers = response.second;
String someHeader = headers.get( "aaaaa" );
...
}
},
new Response.ErrorListener() {...}
);
Related
I'm working on an Android Application that record a speech using the mic of the android device, after that i encode the recorded speech into base64 format. to transform the speech into a text i use google speech cloud api and android Volley to send request to google Api. the probleme is when i call the methode for requesting i got this error ==>
E/Volley: [5921] BasicNetwork.performRequest: Unexpected response code 400 for https://speech.googleapis.com/v1/speech:recognize?key={mykey}
Here is My Code :
public class SpeechService {
private String Url ="https://speech.googleapis.com/v1/speech:recognize?key=${mykey}";
private RequestQueue requestQueue ;
private AppCompatActivity app ;
String savedata ;
public SpeechService(AppCompatActivity app){
this.app = app ;
requestQueue = Volley.newRequestQueue(app.getApplicationContext());
}
public void getTextFromGSpeech1(String EncodedSpeech){
JSONObject jsonObject = new JSONObject();
JSONObject config = new JSONObject() ;
JSONObject audio = new JSONObject() ;
try {
config.put("encoding", MediaRecorder.OutputFormat.AMR_WB);
config.put("SampleRateHertz","rba9 rba9");
config.put("languageCode","fr-FR");
audio.put("content",EncodedSpeech);
jsonObject.put("audio", audio );
jsonObject.put("config", config);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest JObjectREQUEST = new JsonObjectRequest(Request.Method.POST , Url , jsonObject ,new Response.Listener<JSONObject>(){
#Override
public void onResponse(JSONObject response) {
System.out.println("JSON response is ============> ");
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("failed ...............;");
}
}){
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
};
requestQueue.add(JObjectREQUEST);
}
}
and the Json object format must be like this
{ "audio": {
"content": ""
}
,
"config": {
"encoding": "ENCODING_UNSPECIFIED",
"languageCode": "fr-FR",
"sampleRateHertz": 1600
}
}
It should be RecognitionConfig.AudioEncoding.AMR_WB, not MediaRecorder.OutputFormat.AMR_WB. Sample rate is also wrong.
This is more of a style thing, and a self-study thing, but In the volley code are listeners, and all the code I find online involve just nesting a override method inside the constructor. Not necessarily something I'm used to from a C# background. Actually not too great at lambda, anonymous methods neither.
I have no idea where to start, because it doesn't seem intuitive to me right now. But I'd like to separate out nested methods to their own respective methods. Or maybe even just the overridden methods if that is the only part that is needed.
final EditText textView = (EditText) findViewById(R.id.editText);
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://myURL";
JSONObject postparams = new JSONObject();
postparams.put("city", "london");
postparams.put("name", "bob");
// Request a string response from the provided URL.
JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, url, postparams,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
textView.setText("Success: "+ response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
textView.setText(String.valueOf(error.networkResponse.statusCode));
}
}
);
// Add the request to the RequestQueue.
queue.add(postRequest);
What I would like is to name a method in the 2 Response arguments within the same class or maybe this itself to do the override. Is it possible? Something like.
...
JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, url, postparams, myResponseListener(JSONObject response), myErrorResponseListener(VolleyError error));
// Add the request to the RequestQueue.
queue.add(postRequest);
}
public void myResponseListener(JSONObject response){
textView.setText("Success: "+ response.toString());
}
public void myErrorResponseListener(VolleyError error){
textView.setText(String.valueOf(error.networkResponse.statusCode));
}
Is there a simple way to something like this?
Edit: Trying linucksrox answer, to my surprise, the following actually stands alone as its own method... without a public(access modifier) or void(return type)??
Response.Listener<JSONObject> myListener(JSONObject response)
{
return new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
textView.setText("Success: "+ response.toString());
}
};
}
But when I try to plug in myListener as the 4th argument, it complains about the arguments.
myListener() no work,
myListener(JSONOBject response) no work
The same is for the error section argument.
You should be able to do something like this:
Response.Listener<JSONObject> myListener = new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
textView.setText("Success: "+ response.toString());
}
};
Response.ErrorListener myErrorListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
textView.setText(String.valueOf(error.networkResponse.statusCode));
}
};
// Request a string response from the provided URL.
JsonObjectRequest postRequest = new JsonObjectRequest(Request.Method.POST, url, postparams,
myListener, myErrorListener);
I think that JSONException only works when it my request fails but when the request is valid (valid username, password) it should redirect me to another activity but instead a JSONException is showing up.
It shows the JSON string received from the server rather than redirecting me to another activity.
This is my onResponse function
#Override
public void onResponse(String response){
try {
JSONObject volleyResponse = new JSONObject(response);
boolean success = volleyResponse.getBoolean("success");
String message = volleyResponse.getString("message");
String UUID = volleyResponse.getString("unique_user_id");
String LLOGIN = volleyResponse.getString("last_login");
String RDATE = volleyResponse.getString("registration_date");
String MONEY = volleyResponse.getString("money");
if(success){
Intent intent = new Intent(Authentication.this, Mainpage.class);
intent.putExtra(KEY_USERNAME, strUsername);
intent.putExtra(KEY_UUID, UUID);
intent.putExtra(KEY_LLOGIN, LLOGIN);
intent.putExtra(KEY_RDATE, RDATE);
intent.putExtra(KEY_MONEY, MONEY);
startActivity(intent);
}
} catch(JSONException e) {
response = response.replace("\"", "");
response = response.replace("status:false,message:", "");
response = response.replace("{", "");
response = response.replace("}", "");
messageText.setText(response);
}
}
JSON Response when it is success:
{"unique_user_id":"4e99a28a-0cb2-30a9-ac51-ccd4629bcef1","last_name":"therealaxis","password":"$2a$10$9qRjW\/vJreCQg3u5dO6eW.8PhZBTpGaPNK5qRIYP.XTx2PVY1yrOi","last_login":"1 week ago","registration_date":"1 week ago","money":"100.00","success":true}
Your JSON Response has no message string, so a JSONException is thrown. If you just want to access the message attribute in case it is present, use JSONObject.has before accessing it.
I'm trying to run a query to search for locations using search query facebok graf api for android.
If I try to run this query in the Graph API Explorer, I get this result.
But programmatically it is impossible. I try to make so:
new GraphRequest(AccessToken.getCurrentAccessToken(),"/search?q=coffee&type=place¢er=37.76,-122.427",null,HttpMethod.GET,new GraphRequest.Callback()
{
public void onCompleted(GraphResponse response)
{
Log.v("HelloFacebook", response.toString());
}
}).executeAsync();
}
i get nothing (param distance must be number)
if I try without distance i get too nothing, but another message (An access token is required to request this resourse and too)
What could be the problem?
Right syntax for search in Facebook graph API:
GraphRequest request = GraphRequest.newGraphPathRequest(
accessToken,
"/search",
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
// Insert your code here
}
});
Bundle parameters = new Bundle();
parameters.putString("type", "place");
parameters.putString("center", "53,27");
parameters.putString("distance", "30000");
request.setParameters(parameters);
request.executeAsync();
The syntax that Vadim Korzun provided did unfortunately not directly work for me. But it gave me some ideas. I wanted to search for people by names. Here the code I impelemted according to the newPlacesSearchRequest(...)-method of the official GraphRequest-class:
AccessToken accessToken = AccessToken.getCurrentAccessToken();
Bundle parameters = new Bundle(2);
parameters.putString("type", "user");
parameters.putString("q", "Albert Einstein");
GraphRequest.Callback wrapper = new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
try {
JSONObject jso = response.getJSONObject();
JSONArray arr = jso.getJSONArray( "data" );
for (int i = 0; i < (arr.length()); i++) {
JSONObject json_obj = arr.getJSONObject(i);
// START: Your code goes here
String id = json_obj.getString("id");
String name = json_obj.getString("name");
// ...
// END: Your code goes here
}
} catch (JSONException e) {
Log.e("name: ", e.getMessage());
}
}
};
GraphRequest gr = new GraphRequest(accessToken, "search", parameters, HttpMethod.GET, wrapper);
gr.executeAsync();
hope this helps...
I use volley Android library, I have create post request than send to my server :
JSONArray jsonRequest = new JSONArray();
for(MyLocation myLocation : ListLocation){
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("serial", myLocation.serial);
jsonObject.put("longitude", myLocation.longitude);
jsonObject.put("latitude", myLocation.latitude);
jsonObject.put("altitude", myLocation.altitude);
jsonObject.put("accuracy", myLocation.accuracy);
jsonObject.put("date", myLocation.date);
jsonRequest.put(jsonObject);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Request a string response from the provided URL.
JsonArrayRequest stringRequest = new JsonArrayRequest(url, jsonRequest,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
dabAcces.dropTable();
Log.d(TAG, "dropTable");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (row > MAX_REGISTER_GPS_DATA) {
Log.d(TAG, "deleteOldestRecord");
dabAcces.deleteOldestRecord();
}
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
But when I read my server information, I can see the post array it's empty, however when I verify jsonarray contents, I see variable to json format. Help me plz
[2015-08-13 09:30:39] local.INFO: POST
[2015-08-13 09:30:39] local.INFO: array ()
[2015-08-13 09:30:39] local.INFO: GET ------------------------------
[2015-08-13 09:30:39] local.INFO: array ()
[2015-08-13 09:30:39] local.INFO: SERVER ------------------------------
[2015-08-13 09:30:39] local.INFO: array (
'REDIRECT_STATUS' => '200',
'CONTENT_TYPE' => 'application/json; charset=utf-8',
'HTTP_USER_AGENT' => 'Dalvik/1.6.0 (Linux; U; Android 4.1.2; M17-G903-A Build/JZO54K)',
'HTTP_HOST' => 'geoloc.com',
'HTTP_CONNECTION' => 'Keep-Alive',
'HTTP_ACCEPT_ENCODING' => 'gzip',
'CONTENT_LENGTH' => '68921',
'PATH' => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
'SERVER_SIGNATURE' => '<address>Apache/2.4.10 (Ubuntu) Server at geoloc.com Port 80</address> 'SERVER_SIGNATURE' => '<address>Apache/2.4.10 (Ubuntu) Server at geoloc.com Port 80</address>
Looking at JsonArrayRequest in volley's source code
public JsonArrayRequest(String url, JSONArray jsonRequest, Listener<JSONArray> listener,
ErrorListener errorListener) {
this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest,
listener, errorListener);
}
It means you need to pass a JsonArray not a JsonObject
Basically you cant use POST method for "JsonArrayRequest".
JsonArrayRequest class can be used to retrieve JSON array but not JSON object and only HTTP GET is supported as of now. As it supports only GET, so if you are to specify some querystring parameters then append those in the URL itself. The constructor does not accept request parameters.
If you want to send data in post method, you can use "JsonObjectRequest" OR "StringRequest".
Small example to send data in POST method using "StringRequest"
StringRequest strReq = new StringRequest(Request.Method.POST,
URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
Log.d(TAG, "Response: " + response.toString());
} catch (JSONException e) {
// JSON error
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("param1", "value1");
params.put("param2","value2");
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq);
you should override getParams() method to pass the data in POST method. Now you will get your data in the server end.