Android Volley multiple POST to server - android

I am using Volley into an android app that sends coordinates from tablet to my server.
When network connection goes down, the app stores data into an SQlite DB on the device and when JobScheduler finds again the connection, this method in the sequel, sends the records not still synced to the server.
private void saveCoordinate(final String android_id, final String latitude, final String longitude, final String timestamp) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, MainActivity.URL_SAVE_COORDINATE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject obj = new JSONObject(response);
if (!obj.getBoolean("error")) {
// delete the synced sign row
db.deleteSyncedCoordinate(timestamp);
}
} 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> params = new HashMap<>();
params.put("android_id", android_id);
params.put("latitude", latitude);
params.put("longitude", longitude);
params.put("timestamp", timestamp);
return params;
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(30000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(stringRequest);
}
}
This is the the same method that works with network connection and normal send, a part from the fact that it deletes record when they have been synced and it does nothing when the send fails.
I have tested the app, in a lot of time and trip, and appears that there are multiple send of coordinates. Sometimes two send, sometimes three, it isn't a regular bug but on, for example, 30 coordinates saved on SQlite and, when connection comes back, sent to server, 3 of the data presents multiple record on the DB.
I've tried to set a Retry Policy, like in the previous code, or connection.setChunkedStreamingMode(0) (that are both solution from other Stackoverflow questions) but it doesn't solve the problem.
Can you help me? I can provide other code parts or info if you need.
Thanks in advance.

Related

Getting error when trying to upload data to server

I have been trying to upload my data from android to my server using java, volley and laravel but I am getting. BasicNetwork.performRequest: Unexpected response code 500. I have used postman to test my api and it is working perfectly well.
What could be the cause?
Java code
RequestQueue queue = Volley.newRequestQueue(this); // this = context
StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
pd.dismiss();
Log.i("error", String.valueOf( response.toString()));
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error
Toast.makeText(SignUpActivity.this, "Network Error. Please Try Again.", Toast.LENGTH_LONG).show();;
}
}
) {
#Override
protected Map<String, String> getParams()
{
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("email", email);
parameters.put("password", password);
parameters.put("vCode", vCode);
parameters.put("phone",phone);
return parameters;
}
};
queue.add(postRequest);
Code 500 means that there's a problem at server side. If you're using laravel you should have a web server (as apache, nginx...) which generates error logs.
Check error logs and there you may find what the error is (maybe your app is sending data in a way that server doesn't understand, data is not being sent properly...).
Apache error log location in Linux
Nginx error log location

Volley JsonObjectRequest POST Request

Peeps, I have some problem in understanding the working of volley library, so answer with proper material which can guide me to unobserved aspects of volley is what I am looking forward to.
How does my POST parameters are bind in network request. When I send params after overriding getParams() and by sending jsonObject directly in network request I don't receive any response but some server errors.
Since I am testing my backend on Postman, what postman actually does(my Observation) is it bind the params in url itself. When I copy paste the url in my android code it responds positively.
So, should I code to append my params to url or there's another way round?
I have alredy tried making changes to getHeaders() but it doesn't respond too!
You should use a JsonObjectRequest with a jsonObject containing all your params.
HashMap<String, String> params = new HashMap<String, String>();
params.put("token", "8327483274823");
JSONObject jsonObject = new JSONObject(params);
JsonObjectRequest req = new JsonObjectRequest(URL,jsonObject ,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
//Do stuff here
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Handle Errors here
}
});

ANDROID: onesignal notifications using tags

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.

BasicNetwork.performRequest: Unexpected response code 429 (android)

I m using Volley library for sending a request to server for Login to an app. it doesn't have any problem until couple of hours ago. but without any reason, i m getting this error "BasicNetwork.performRequest: Unexpected response code 429"
the code is this:
public void loginRequest(final String username, final String password) {
String URL = Misc.Server_Url() + "login";
final StringRequest sr = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONObject obj;
try {
obj = new JSONObject(response);
if (obj.getInt("success") == 1) {
startActivity(new Intent(ActivityLogin.this, ActivityArticles.class));
finish();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("username", username.trim());
params.put("password", password);
return params;
}
};
RetryPolicy policy = new DefaultRetryPolicy(2 * 1000, 2, 2);
sr.setRetryPolicy(policy);
AppController.getInstance().addToRequestQueue(sr);
}
I have searched in Wikipedia for this error (429) and i find that it means : "The user has sent too many requests in a given amount of time"
from server side(php) for more security if from an ip get more than for example 60 request within 10 second it will block that ip for a while... and client get 429 error code. i m wondering how it will occure when i send a single request to server same as above code!!! and in policy i set the try to 2 times Not more than that. i dont know why when i send this request i get error 429. means you have send 60 request within limited period of time.
do you know how to solve this problem?
thanks in advance...
Yes, as you said, the 429 response code states so. However, the tricky part is that the server sends this response code for either
You have sent too many requests in a short duration
The server has received too many requests by many others during that time
If you read the RFC related to the response code, you'll see that the RFC does not state that the server must identify individual users and only send them the busy status: 429. It could be because others are sending too many requests and the server is sending a 429 response to all.
In addition, the RFC states that the server should respond with a 429 response and the server MAY send the following parameter in its response header.
Retry-After: 3600
This would mean you should retry after this timeout.
the reason was coz of caching system in server.
if we send new request each time, it works fine. but if our request use from caching strategy system in server... it occur 429 error number...

Android Volley access caching response data

I'm using Volley library to access my server data.Volley has inbuilt caching function.I tried to use that as follows.this out put "CACHED RESPONSE". but i don't know how to access the cached data.
void initHttpCall(){
RequestQueue queue = Volley.newRequestQueue(mcontext);
UOBRequest<RateData> myReq = new UOBRequest<RateData>(Method.GET,
Constants.GET_RATES,
RateData.class,
mlistner,
createMyReqErrorListener()){
#Override
public Map<String, String> getHeaders(){
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", getToken());
headers.put("Accept","application/json" );
return headers;
}
};
myReq.setShouldCache(true);
if(queue.getCache().get(Constants.GET_RATES)!=null){
System.out.println("CACHED RESPONSE");
}else{
queue.add(myReq);
}
}
}
This is my response listner and want to get RateData object here.
new Response.Listener<RateData>() {
#Override
public void onResponse(RateData rateData) {
setupCurrencyPager(rateData);
setLastUpdatedTime();
}
});
You misunderstood how Volley's caching system works. The beauty of it is that as a user of Volley, you are unaware of where the response is coming from.
When you add a new request to the RequestQueue, Volley checks if that request already has a cached response. If it does, and that response has not expired yet, it is returned immediately. Otherwise, it goes outside to the network, retrieves the response, caches it and returns it to you.
You don't need that last if statement, simply add it to the queue and Volley will take care of the rest.
try the following code.it will help you sure.
please create a request which you want to pass to server.
JSONObject request = new JSONObject();
request.put("user","user2");
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, url, request, new Response.Listener() {
#Override
public void onResponse(JSONObject response) {
// TODO Auto-generated method stub
Log.v("response:-"+response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsObjRequest);
}

Categories

Resources