Verification of http post - android

I'm using the following code to post to a Google Form. If the HTTP response is not successful then the record is not marked as sent from the sqlite database and is resent during the next sync operation. The problem is I see frequent double posts because a response is not received even though the post was successful.
Is there a better way to confirm the post without creating double posts to the form?
Thanks for your help.
private Boolean performPost(String...data){
prefs = UserData.getPrefs(mContext);
spreadsheetKey = prefs.getString(UserData.PREF_SPREADSHEET_KEY,"");
ArrayList<BasicNameValuePair> results = new ArrayList<BasicNameValuePair>();
HttpPost post = new HttpPost("https://spreadsheets.google.com/spreadsheet/formResponse?hl=en_US&formkey=" + spreadsheetKey);
int counter = 0;
for (String s : data){
results.add(new BasicNameValuePair("entry." + counter + ".single", s));
counter ++;
}
try {
post.setEntity(new UrlEncodedFormEntity(results));
} catch (UnsupportedEncodingException e) {
// Auto-generated catch block
Log.e(TAG, "An error has occurred", e);
}
try {
//client.execute(post);
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
returnCode = statusLine.getStatusCode();
Log.d(TAG, statusLine+ "\n"+ returnCode + " " + String.valueOf(post.getEntity()));
response.getEntity().consumeContent();
} catch (ClientProtocolException e) {
// Auto-generated catch block
Log.e(TAG, "client protocol exception", e);
} catch (IOException e) {
// Auto-generated catch block
Log.e(TAG, "io exception", e);
}
if (returnCode == 200){
return true;
}else{
resultTxt = SYNC_UNSUCCESSFUL_HTTP_ERROR;
Log.e(TAG,"post unsuccessful, http code :" + String.valueOf(returnCode));
sendBroadcast();
return false;
}
}

Related

HttpURLConnection POST response gets lost when server takes longer to respond

I'm having trouble catching a response to a POST request to server, when the server takes a bit longer to respond (when it is passed a bigger JSONObject).
When we call a GET method with a longer response time, there is no problem. When we call a POST and pass a relatively small JSONObject, the method registers a response.
The method is being called from an AsyncTask via new Task().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).
When triggered from Postman, the response returns after 155 seconds, but it arrives. On the other hand, when triggered from the app, the code does nothing and ultimately tiggers a SocketTimeoutException.(For whatever reason, we have a timeout(connection and read timeout) set to 10 minutes) The code snippet for the service method is below. I'd appreciate any hints.
public static JSONObject requestWebService(String serviceUrl, JSONObject jsonObject) throws Exception {
private static final int CONNECTION_TIMEOUT = 1000 * 600;
private static final int DATARETREIVAL_TIMEOUT = 1000 * 600
HttpURLConnection urlConnection = null;
try {
URL urlToRequest;
String message;
urlToRequest = new URL(serviceUrl);
urlConnection = (HttpURLConnection) urlToRequest.openConnection();
urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
urlConnection.setReadTimeout(DATARETREIVAL_TIMEOUT);
if (jsonObject != null) {
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
message = jsonObject.toString();
OutputStream os = new BufferedOutputStream(urlConnection.getOutputStream());
os.write(message.getBytes());
os.flush();
os.close();
} else {
urlConnection.setRequestMethod("GET");
}
int statusCode = urlConnection.getResponseCode();
if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
throw new Exception("Acces unauthorized " + statusCode + ".");
} else if (statusCode != HttpURLConnection.HTTP_OK) {
throw new Exception("Server unavailable " + statusCode + ".");
}
return new JSONObject(ReplicationClient.convertInputStreamToString(urlConnection.getInputStream()));
} catch (MalformedURLException e) {
fileLogger.error(logHeader + e.getMessage(), e);
throw new Exception("Error " + e.getMessage(), e);
} catch (SocketTimeoutException e) {
fileLogger.error(logHeader + e.getMessage(), e);
throw new Exception("Error " + e.getMessage(), e);
} catch (IOException e) {
fileLogger.error(logHeader + e.getMessage(), e);
throw new Exception("Error " + e.getMessage(), e);
} catch (JSONException e) {
fileLogger.error(logHeader + e.getMessage(), e);
throw new Exception("Error " + e.getMessage(), e);
} catch (Exception e) {
fileLogger.error(logHeader + e.getMessage(), e);
throw new Exception("Error " + e.getMessage(), e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
after a second thought i have a theory
i will explain in details
but first try this code for writing data:
remove this from your code:
OutputStream os = new BufferedOutputStream(urlConnection.getOutputStream());
os.write(message.getBytes());
os.flush();
os.close();
use this:
OutputStream os = urlConnection.getOutputStream();
os.write( message.getBytes());
os.close();
if this works, then i will edit this answer and explain more.
This answer did not help as per the OP comment.
I am keeping this in case i found something else, otherwise, i will delete it later.

most of the time get connection reset by peer exception in my android app

When I run the following code, I get a "connection reset by peer" exception in most instances.
String rest = System.setProperty("http.keepAlive", "false");
String uri = WEB_LOG_IN + "?user_username=" + user_email
+ "&user_password=" + user_pass + "&user_mac=" + user_mac;
HttpClient client = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uri);
HttpResponse response;
String s;
try {
response = client.execute(httppost);
s = new String(EntityUtils.toByteArray(response.getEntity()),
"UTF-8");
// read json
if (s.length() > 2)
return readlogin_info(s);
else
return false;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
String rest = System.setProperty("http.keepAlive", "false");
returns null which means no "http.keepAlive" property.
I tried using httpurlconnection, but that also didn't work.
I am so confused because I think the code works without issue for some ISPs.
Based on my investigation the exception caused by Mikrotik Router latency! (Maybe! Please correct me if I am wrong!)
so I put the execute section in a while until it can get the answer from server, after multiple execution I see after 2 times of trying to connect it successfully get the answer.
int count = 0;
while (s == null) {
count++;
try {
response = client.execute(httpGet);
s = new String(
EntityUtils.toByteArray(response.getEntity()),
"UTF-8");
// read json
if (s.length() > 2)
{
return readlogin_info(s);
}
else
{
return false;
}
} catch (Exception e) {
e.printStackTrace();
}

Very slow retrieval on android with 3G connection. Not with HSDPA or WiFi or on emulator

This is a bit of a complicated question as I do not know the exact problem. The main issue is that it takes a very long to get a very small package of data from our REST server from our Android app. I will describe it in detail and hope you can help me.
Problem
Data retrieval is fast enough (+/- 100ms) when:
Connected with WiFi
Connected with HSDPA
Running on Android Emulator with network settings (delay and speed) set to GPRS
However, when I use a phone on a location with bad connection (3G instead of HSDPA) calling the services can take up to 4s (current timeout on the AsyncTask).
Android
This is the code used to communicate with the services:
/**
* Get json string from service
*
* #param urlString url of service
* #return json result from service
*/
private String callService(String urlString) {
InputStream in = null;
HttpURLConnection c = null;
Scanner s = null;
String json = null;
try {
URL url = new URL(urlString);
Log.i(getClass().getName() + ".callService()", "start calling service: " + url);
long start = java.lang.System.currentTimeMillis();
try {
setAuthentication();
c = (HttpURLConnection) url.openConnection();
c.connect();
in = new BufferedInputStream(c.getInputStream());
s = new Scanner(in);
s.useDelimiter("\\A");
json = s.next();
} catch (IOException e) {
Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
}
Log.i(getClass().getName() + ".callService()", "complete calling service: (" + (System.currentTimeMillis() - start) + " ms) " + url);
return json;
} catch (Exception e) {
Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
} finally {
if (s != null) {
s.close();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
}
}
if (c != null) {
c.disconnect();
}
}
return json;
}
I have tried several ways to call this, but currently this is done using an AsyncTask:
/**
* Retrieve json from service
*
* #param url url of service
* #return json
*/
public String getJsonFromServiceBasic(String url) {
ServiceTask task = new ServiceTask();
try {
return task.execute(url).get(4000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " interrupt exception: " + e.getMessage(), e);
} catch (ExecutionException e) {
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " execution exception: " + e.getMessage(), e);
} catch (TimeoutException e) {
task.cancel(true);
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " timeout exception: " + e.getMessage(), e);
} catch (Exception e) {
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " timeout exception: " + e.getMessage(), e);
}
return null;
}
/**
* AsyncTask way of calling service
*/
class ServiceTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String json = callService(urls[0]);
return json;
}
}
AndroidManifest.xml:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Services
I do not think this is the issue, as it works fast enough with HSDPA, but I am not sure.
Restlet services on tomcat7 behind a proxy. We're using a ChallengeAuthenticator for authentication.
I have solved this problem by switching to Apache's HttpClient.
I am not sure why this is a solution as Google suggests using the HttpURLConnection, but for me this works.
Using this method instead of the callService method will solve my troubles with slow internet access.
private String callServiceClient(String urlString) {
String json = null;
HttpParams httpParams = new BasicHttpParams();
int connection_Timeout = 5000;
HttpConnectionParams.setConnectionTimeout(httpParams, connection_Timeout);
HttpConnectionParams.setSoTimeout(httpParams, connection_Timeout);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
httpClient.getCredentialsProvider().setCredentials(new AuthScope(null, -1),
new UsernamePasswordCredentials(user, password));
HttpGet httpget = new HttpGet(urlString);
// Execute the request
HttpResponse response;
try {
response = httpClient.execute(httpget);
// Examine the response status
StatusLine responseCode = response.getStatusLine();
Log.i(getClass() + ".callServiceClient()", "responsecode: " + responseCode);
if (responseCode.getStatusCode() != HttpStatus.SC_OK) {
return json;
}
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
json = convertStreamToString(instream);
// now you have the string representation of the HTML request
instream.close();
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
e.printStackTrace();
}
return json;
}

Android HttpGet is requesting indexAction

my HttpGet request is calling my indexAction, instead of getAction. What's going on?
Here are my codes:
public function getAction() {
$id = $this->_getParam('id');
if(!$id)
{
$this->getResponse()
->setHttpResponseCode(400)
->setBody("no id");
return;
}
try
{
$q = Doctrine_Query::create()
->from('Milotin_Model_Locations l')
->where ('l.id=?', $id);
$result = $q->fetchArray();
if(count($result) == 1)
{
$this->getResponse()
->setHttpResponseCode(200)
->setBody(json_encode($result));
}
}
catch(Exception $e)
{
$this->getResponse()
->setHttpResponseCode(500)
->setBody($e->getMessage());
}
}
public function indexAction() {
}
And here is my code in Android:
private static void getLoc()
{
final HttpResponse response;
final HttpGet getRequest = new HttpGet(LOCATION_URI + "?geolat=" + geoLat + "&geolong=" + geoLong);
try {
response = mHttpClient.execute(getRequest);
if(response.getStatusLine().getStatusCode() == 200)
{
//do something
}
} catch (ClientProtocolException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
}
My HttpPost is working correctly (it calls postAction), Any explanation?
Thanks.
I found the answer. It's actually the behavior of Zend Framework. If the 'id' element is not found in the GET request, it will redirect to indexAction, instead of getAction.
Example:
'GET localhost/student' will redirected to indexAction, while
'GET localhost/student/23' will redirected to getAction. (23 is the id)
Found it in Zend Framework: A beginner's guide, by Vikram Vaswani.

How to access SOAP web services in Android

I tried to access soap Ws using httpPost;this my code
HttpPost httpPost=new HttpPost(WebService Url);
httpPost.addHeader("Content-Type", "application/soap+xml; charset=utf-8");
httpPost.addHeader("Host", HostName);
//get from the getflashinfo method;
String soapRequestXml=getFlashInfo(0);
Log.d("Message12", soapRequestXml);
try
{
StringEntity se=new StringEntity(soapRequestXml, HTTP.UTF_8);
se.setContentType("text/xml");
httpPost.setEntity(se);
HttpClient hC=new DefaultHttpClient();
HttpResponse reponse=hC.execute(httpPost);
Log.d("Message12", response.toString());
}
catch (ClientProtocolException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Second Function
String getFlashInfo(int target)
{
String sHeaderRequest="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">"+
"<s:Header>" +
"<a:Action s:mustUnderstand=\"1\">http://tempuri.org/IFlashInfoService/GetFlashInfo</a:Action>" +
"<a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo>" +
"<a:To s:mustUnderstand=\"1\">URL</a:To>" +
"</s:Header>" +
"<s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
"<GetIdTargetRequest xmlns=\"http://tempuri.org/\">" ;
String sHeaderRequest1;
if (target > 0)
{
sHeaderRequest1="<IdTarget>"+" "+target+" "
+"</IdTarget>";
}
else
{
sHeaderRequest1="<IdTarget>0</IdTarget>";
}
sHeaderRequest=sHeaderRequest+sHeaderRequest1;
sHeaderRequest=sHeaderRequest+"</GetIdTargetRequest>";
sHeaderRequest=sHeaderRequest+"</s:Body>";
sHeaderRequest=sHeaderRequest+"</s:Envelope>";
Log.d("Message12", sHeaderRequest);
return sHeaderRequest;
}
I got Null Pointer exception when try to log the reponse message
I used Ksop library with
got some kind of xmlparse error and unknown source exception
Please Help me
Regards,
Kariyachan
I am posting a video tutorial, this might help
http://www.vimeo.com/9633556
Happy Coding!

Categories

Resources