I am trying to sent JSON format data (using Volley) from two EditText-views and a method that return unique Device ID to a URL from my Android application and I receive
"[8970] BasicNetwork.performRequest: Unexpected response code 401 for https://gorountsiallyetlasornall:5wxGq5UNlY6wdWmNAyYPVVrN#bulberadev.cloudant.com/notebook"
Here is My method:
private void doPost() {
final String url = "https://gorountsiallyetlasornall:5wxGq5UNlY6wdWmNAyYPVVrN#bulberadev.cloudant.com/notebook";
final String deviceId = getDeviceId(getApplicationContext());
try {
try {
JSONObject jsonObject = new JSONObject();
String title = editTitle.getText().toString();
String content = editContent.getText().toString();
jsonObject.put("title", title);
jsonObject.put("content", content);
jsonObject.put("deviceId", "<" + deviceId + ">");
} catch (JSONException e) {
e.printStackTrace();
}
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,
url, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
VolleyLog.v("Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Log.e("VOLLEY", "ERROR");
}
});
requestQueue.add(jsonObjectRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
it should be in a format :
{
"title":"Birth day",
"content":"Buy a gift for my mom!",
"deviceId":"<Device ID>"
}
A 401 is an Unauthorized error.
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error
This means that the user and password is not getting recognized. You're providing it by means of the URL, but this only works for the browser. If the service you're using accepts Basic HTTP authorization headers, this code will provide you the needed headers:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String creds = String.format("%s:%s","USERNAME","PASSWORD");
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.DEFAULT);
params.put("Authorization", auth);
return params;
}
Original code from https://stackoverflow.com/a/18980454/3286819
Of course, username and password needs to be your own. In this case:
username: gorountsiallyetlasornall
password: 5wxGq5UNlY6wdWmNAyYPVVrN
URL: https://bulberadev.cloudant.com/notebook (notice I've removed the user and password)
Some more info: https://yakivmospan.wordpress.com/2014/04/04/volley-authorization/
Error 401 is an HTTP error for unauthorised. This is not a Volley or android related fault. In this case the URL you have provided
https://gorountsiallyetlasornall:5wxGq5UNlY6wdWmNAyYPVVrN#bulberadev.cloudant.com/notebook
Cannot be interpreted by Volley as a login either. This url is sometimes used by cURL and other tools to hardcode the username in password into the URI for Basic Authentication HTTP.
For this your username is gorountsiallyetlasornall and your password is 5wxGq5UNlY6wdWmNAyYPVVrN.
According to Basic Autentication, explained https://luckymarmot.com/paw/doc/HTTP_Basic_Auth
It needs to be converted to Base 64 then added to the header of the request.
I have converted your username and password into a Basic Auth base 64 encoded String for you bellow.
Z29yb3VudHNpYWxseWV0bGFzb3JuYWxsOjV3eEdxNVVObFk2d2RXbU5BeVlQVlZyTg==
Add this into your Volley header by extending a Volley request and overriding the function getHeaders to return a HashMap with the following key value pair.
"Authorization" , "Basic Z29yb3VudHNpYWxseWV0bGFzb3JuYWxsOjV3eEdxNVVObFk2d2RXbU5BeVlQVlZyTg"
Your request will now work.
Please let me know if you want a more detailed explanation.
PS. Hopefully the values you posted in your question is not your real username and password. If so, then don't do that in the future.
Related
I am using Volley Library for JSON Parsing, while parsing the response coming is as below :
JSON RESPONSE :
{"category":{"420":{"key":420,"label":{"420":"Acacia"},"count":"1"},"421":{"key":421,"label":.....
We can see, at start of the response a symbol is coming  . How can I remove this symbol from Android side without converting it into string? Because of this symbol I am not able to get JSON Object.
CODE :
private void jsonRequestGetFilterData() {
utils.showDialog();
String url = Constants.FILTER_URL;
Log.e("URL", "" + url);
StringRequest eventoReq = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("RESPONSE", response);
utils.hideDialog();
try {
JSONObject jsonObject = new JSONObject(response);
Log.e("jsonObject",""+jsonObject);
JSONObject jsonObjectCategory = jsonObject.getJSONObject("category");
Log.e("jsonObjectCategory",""+jsonObjectCategory);
} catch (JSONException e) {
e.printStackTrace();
utils.hideDialog();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error: ", "" + error.getMessage());
utils.hideDialog();
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting parameters to login url
Map<String, String> params = new HashMap<String, String>();
params.put("customer_id", pref.getString(Constants.SP_CUSTOMER_ID, ""));
params.put("store_id", pref.getString(Constants.SP_STORE_ID, ""));
params.put("currency_code", pref.getString(Constants.SP_CURRENCY_CODE, ""));
Log.e("customer_id",""+pref.getString(Constants.SP_CUSTOMER_ID, ""));
Log.e("store_id",""+pref.getString(Constants.SP_STORE_ID, ""));
Log.e("currency_code",""+pref.getString(Constants.SP_CURRENCY_CODE, ""));
return params;
}
};
eventoReq.setRetryPolicy(new DefaultRetryPolicy(
60000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
AppController.getInstance(FilterActivity.this).addToRequestQueue(eventoReq);
}
Your response starts with a byte-order mark (BOM). At the level where you're reading the response, you need to ensure that the stream or whatever you're using to do that knows the encoding of the response (apparently it's not auto-detecting it). When it knows the correct encoding, it should understand and handle the BOM.
Normally, this is handled via the Content-Type header in the response from the server, and that's where it should be fixed. But if for some reason you can't fix it there, usually there's an option when creating the read stream to force an encoding. Yours looks like UTF-8.
Don't just use substring or similar to skip over it. Other characters in the string may well have been interpreted incorrectly because the wrong encoding is being used. (This isn't just for obscure characters, the £ sign varies by encoding, as does the € and any number of others.)
More: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
Solution 1:
The characters  is the byte order mark , so you should check your encoding (UTF-8 with or without BOM).
Solution 2:
You can convert response string to UTF-8 like,
#Override
public void onResponse(String response) {
try {
response=new String(response.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Log.e("RESPONSE", response);
...................
}
I find a simplest solution for my question. Put below line of code when you are sending params for POST Request.
Code Here :
params.put("Content-Type", "application/json; charset=utf-8");
Full Code :
----------
#Override
protected Map<String, String> getParams() {
// Posting parameters to login url
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json; charset=utf-8");
params.put("username", email.getText().toString().trim());
params.put("password", pwd.getText().toString().trim());
return params;
}
I am creating push notifications using onesignal,I send push notifications by player ids but it has a limitation.
I have a login system and i want to send notifications for different users and if two or more users login from same device then i can't differentiate between them.
Right now i have a table and whenever user logins it adds the playerid to that user and then through php I send notifications by playerId which is in the user table
I searched a lot and couldn't find a solution
May be your approach is wrong you need to de-register user as soon as user logs out.
Simple words you need to remove that user from device ID table when ever user do logout.
You can add tags to users and send notifications based on tags attached to different users and send notifications to them by making a POST using the URL https://onesignal.com/api/v1/notifications
Segments can be created only by using the OneSignal dashboard, but tags can be created by using the SDK/API.
Add Headers "Content-Type":"application/json" and "Authorization":"Basic <REST API Key>"
In body add
{
"app_id":"<App Id>",
"headings":{
"en":"Title Here"
},
"contents":{
"en":"Description Here"
},
"filters":[
{
"field":"tag",
"key":"level",
"relation":"=",
"value":"10"
},
{
"operator":"OR"
},
{
"field":"amount_spent",
"relation":">",
"value":"0"
}
]
}
Then make a JSON object request to complete the process.
You can refer the following code to see how to attach headers to a JSON object request & to attach tags to your users. (This request has been made by using android volley)
String url = "https://onesignal.com/api/v1/notifications";
JSONObject jsonBody;
try {
jsonBody = new JSONObject(
"{'app_id':'app-id'," +
"'headings': {'en': 'title'}, " +
"'contents': {'en': 'message'}," +
"'filters':[{'field':'tag','key':'"+id+"','relation':'=','value':'true'}]}"
);
//request a json object response
JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.POST, url, jsonBody, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//now handle the response
Toast.makeText(Activity.this, "Notification successfully sent", Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//handle the error
Toast.makeText(Activity.this, "An error occurred", Toast.LENGTH_SHORT).show();
error.printStackTrace();
}
})
{ //adding header to the request
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<String, String>();
params.put("Authorization", "Basic <REST API KEY>");
params.put("Content-type", "application/json");
return params;
}
};
// Add the request to the queue
Volley.newRequestQueue(Activity.this).add(jsonRequest);
} catch (JSONException e) {
e.printStackTrace();
}
Attaching tags to a user
JSONObject tags = new JSONObject();
try {
tags.put("key","value");
//for the above JSON request I have used the following key value pair
// tags.put(id,true);
// where id is a string containing the userId
//true is a boolean value
} catch (JSONException e) {
e.printStackTrace();
}
OneSignal.sendTags(tags);
This should successfully complete your query.
So I'm running into a problem when calling rest-auth/user/.
I am able to login and obtain the key from said login, but from that I'm not sure how to use it in regards to rest-auth/user/. I've tried using it with GET in volley, as well as POSTing it in volley. But everytime I try to do so, I get a 403 back saying credentials were not provided. I've also tried saving the token to Android's SharedPreferences.
I'm not sure what could be wrong or how to fix this problem, so any help would be appreciated.
My code looks like this:
getUserQueue = Volley.newRequestQueue(this);
JSONObject jsObj = new JSONObject();
try {
jsObj.put("token", token);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, "http://hurst.pythonanywhere.com/supportal/rest-auth/user/", jsObj, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
result = response.getString("username");
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
// add the request object to the queue to be executed
getUserQueue.add(jsObjRequest);
From comments it is clear that you are using different authentication schemes for rest, will explain these,
SessionAuthentication
For authenticating session authentication you need persistant cookie implementation in android volley, check here for this, where Set-Cookie header is parsed from server api response & send over next requests.
BasicAuthentication
In Basic authentication scheme, username & password are send over every request ( after login ?), with Authorization header value ( Base64 encoded).To check how to implement this check here
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String creds = String.format("%s:%s","USERNAME","PASSWORD");
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.DEFAULT);
params.put("Authorization", auth);
return params;
}
JSONWebTokenAuthentication
In JWT authentication scheme, after successful login you will get a JWT token, you need to send this token in every request that need user authorization, for this to work, set Authorization header value with JWT token_after_login;Only difference with Basic authentication is how header is send.
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String auth = "JWT " + token // token you will get after successful login
params.put("Authorization", auth);
return params;
}
I'm trying to make a GET request in an Android application using the Volley library. This GET request is to verify account credentials using Basic HTTP Authentication. I verified the URL with credentials works in my browser as it returns successful XML. The format is:
http://username:password#myanimelist.net/api/account/verify_credentials.xml
where username and password obviously represent real user credentials. Volley throws this error:
BasicNetwork.performRequest: Unexpected response code 401 for http://username:password#myanimelist.net/api/account/verify_credentials.xml
Here is my Android code that handles the request:
private static final String HTTP_PRE = "http://";
private static final String VERIFY_CREDENTIALS = "myanimelist.net/api/account/verify_credentials.xml";
public void verifyCredentials(String username, String password) {
RequestQueue queue = Volley.newRequestQueue(context);
String url = HTTP_PRE + username + ":" + password + "#" + VERIFY_CREDENTIALS;
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
processResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// handle error
Log.d(TAG, "error: " + error.getMessage());
}
});
queue.add(stringRequest);
}
This solution to override the getHeaders() method provided the same result:
How does one use Basic Authentication with Volley on Android?.
Here is my implementation of that solution:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = super.getHeaders();
if (params == null){
params = new HashMap<>();
}
String creds = String.format("%s:%s", username, password);
params.put("Authorization", creds);
return params;
}
Which returned this error without the credentials built directly into the URL:
BasicNetwork.performRequest: Unexpected response code 401 for http://myanimelist.net/api/account/verify_credentials.xml
If someone could provide advice, I'd really appreciate it. This is my first time using Basic HTTP Authentication so I could be missing something obvious.
I solved this problem following the first answer here: Http Authentication in android using volley library. I had tried something similar and many other solutions but this was the only one that worked.
Basic Authentication uses BASE64 encoding. You're missing
String creds = String.format("%s:%s", username, password);
creds = Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
The Authorization HTTP header requires to indicate the method used (Basic|Digest). At last you headers should look like this:
GET http://username:password#myanimelist.net/api/account/verify_credentials.xml
Accept: text/xml,text/plain
...
Authorization: Basic XXXXXXXXXXXXXX==
Every time I try to use POST method with Volley, I get sever error. I get null value in getCause, and some default value in getNetworkResponse.toString().
If I use GET method, this works fine (I get response from my url).
Can anybody help what can I do?
Map<String, String> jsonParams = new HashMap<String, String>();
jsonParams.put("teststr", "abd");
RequestQueue requestQueue = VolleySingleton.getInstance().getRequestQueue();
JsonObjectRequest request = new JsonObjectRequest(
Request.Method.POST,
url,
new JSONObject(jsonParams),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Toast.makeText(getApplicationContext(), "Success"+response.toString(), Toast.LENGTH_LONG).show();
}catch(Exception e){
Toast.makeText(getApplicationContext(), "JSON ERROR", Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("abd", "Error: " + error
+ ">>" + error.networkResponse.statusCode
+ ">>" + error.networkResponse.data
+ ">>" + error.getCause()
+ ">>" + error.getMessage());
}
}) {
#Override
protected Map<String,String> getParams() {
HashMap<String, String> params = new HashMap<String, String>();
params.put("key", "value");
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
};
requestQueue.add(request);
Error Log:
Error:
Error: com.android.volley.ServerError>>404>>[B#42b1e0d0>>null>>null
UPDATE:
networkResponse.statusCode comes as 404, though the url is accessible (and return data if I just use GET method). If I remove header part in POST method, still the same.
the url:
<?php
$response = array();
$jsonString = file_get_contents('php://input');
$jsonObj = json_decode($jsonString, true);
if(!isset($jsonObj['teststr'])){
$response["msg"] = "No data.";
}else{
$response["msg"] = "Success: ".$jsonObj['teststr'];
}
echo json_encode($response);
?>
problem is your Queue.
change your volley code to this:
RequestQueue queue = Volley.newRequestQueue(this);
String URL = EndPoints.BASE_URL + "/call";
StringRequest request = new StringRequest(Request.Method.POST, URL,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
Log.d("onResponse", response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
NetworkResponse response = error.networkResponse;
String errorMsg = "";
if(response != null && response.data != null){
String errorString = new String(response.data);
Log.i("log error", errorString);
}
}
}
) {
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("key_1","value_1");
params.put("key_2", "value_2");
Log.i("sending ", params.toString());
return params;
}
};
// Add the realibility on the connection.
request.setRetryPolicy(new DefaultRetryPolicy(10000, 1, 1.0f));
// Start the request immediately
queue.add(request);
and your php (laravel) code to this:
$response['success'] = true;
$response['user']['tell'] = $user->tell;
$response['user']['code'] = $user->code;
$response['user']['time'] = $time;
$response['user']['register_state'] = '1'
return response()->json($response, 200);
First, try to make sure your server works well.
You can use Postman(chrome plug-in) or any other way to send a post request to the url and see what it responses.
After make sure there's no problem with your server, let us solve the problem with volley.
There's some problem with JsonObjectRequest when you use POST method.
like this Volley JsonObjectRequest Post request not working.
I suggest you use StringRequest first and overwrite the getParams method like you did before. After you survive this task, you can try to write your own request, not very difficult but very useful.
I also suggest add request.setShouldCache(false) before requestQueue.add(request);. By default, volley saves the response in its cache and this behavior may cause some strange problem.
Well,I think you can first print the responseCode in your logcat
Add this code before add to queue
request.setRetryPolicy(new DefaultRetryPolicy(0, -1,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
sometimes, request is timeout before your php executed completely. so try this code. maybe can help
maybe it's related to your operator...
I have the same issue sending JasonObject with Volley.
I tested my app on 9-10 devices with two different operators.
The request on one operator returns an Error with everything null or blank data in it, on the other one everything works fine and I get my Response from API successfully.
I have no idea what do operators do that causes this problem...
Maybe they use some kind of firewall that blocks sending JsonObject.
I tried to display the response as a String and the error went off.
Use response.toString() wherever you want to display the error or use it.
In my case, the answer is retry policy setting.
I put 30 seconds the timeout value, it should be 30000, not 30.
try to increase timeout. i had the same issue and the request timeout was the problem.