How to avoid to Time out Exception? - android

I'm trying to create an android application which depends on JSON responses. Sometimes it takes a lot of time for the server to respond and ends in a time out exception. Therefore I would like to add a restriction like my webservice call should abort after 20seconds if there is no response. Can you please help me achieving this idea.
Thanks in Advance.

You're not giving much details on the actual implementation that you have.
However, messing with the timeout seems like it may be an emergency fix to an underlying problem that should be fixed.
However, using websockets for transport could be a possible (and probably more elegant) solution. They provide a persistent connection between client and server once created.
Using websockets on Android and IOS

There are several ways to achieve the goal.
We can using HttpURLConnection to do the http request.
public String doPost() {
if (!mIsNetworkAvailable) {
return null;
}
try {
URL url = new URL(mURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
for (String key : mHeadersMap.keySet()) {
conn.setRequestProperty(key, mHeadersMap.get(key));
}
conn.setRequestProperty("User-Agent", "Android");
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setRequestProperty("Content-Type", "application/json");
conn.getOutputStream().write(mContent);
conn.getOutputStream().flush();
int rspCode = conn.getResponseCode();
if (rspCode >= 400) {
return null;
}
byte[] buffer = new byte[8 * 1024];
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
while ((len = bis.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
baos.flush();
final String result = new String(baos.toByteArray());
baos.close();
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
setConnectTimeout :Sets the maximum time in milliseconds to wait while connecting.
setReadTimeout:Sets the maximum time to wait for an input stream read to complete before giving up.
Reference: http://developer.android.com/reference/java/net/URLConnection.html

Related

Content length is not found in this URL

String thisurl ="http://songolum.com/file/ppdVkTxqhwcJu-CAzCgtNeICMi8mHZnKQBgnksb5o2Q/Ed%2BSheeran%2B-%2BPerfect.mp3?r=idz&dl=311&ref=ed-sheran-perfect";
url = null;
try {
url = new URL(thisurl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
// urlConnection.setRequestProperty("Transfer-Encoding", "chunked");
urlConnection.setRequestProperty("Accept-Encoding", "identity");
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0);
int l=0;
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
while(in.read()!=-1)
{
l=l+in.read();
}
System.out.println("Content-length" +l);
**I checked with other software and I found it's gzip compressed file and its with 10mb and I'm getting almost 1mb **
To answer your question directly, you were going wrong because you were calling read() twice, and also because you were adding together the values of each byte read, instead of counting them. InputStream.read() reads one byte and returns its value, or -1 on EOF. You need to read a number of bytes into a buffer and count how many bytes each read() call returned:
InputStream in = urlConnection.getInputStream();
byte[] buffer = new byte[4096];
int countBytesRead;
while((countBytesRead = in.read(buffer)) != -1) {
l += countBytesRead;
}
System.out.println("Content-length: " + l);
However, I suspect that this is not really what you need to do. The above code will simply return the size of all content in the response, including the HTTP headers and the content. Perhaps what you are looking for is the length of the document (or the file to be downloaded). You can use the Content-length HTTP header for that purpose (see other SO questions for how to get HTTP headers).
Also, note that the content may or may not be gzip-compressed. It depends on what the HTTP request says it accepts.
Please try this one hope so it will be helpful for you.
Using a HEAD request, i got my webserver to reply with the correct content-length field which otherwise was wrong. I don't know if this works in general but in my case it does:
private int tryGetFileSize(URL url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("HEAD");
conn.getInputStream();
return conn.getContentLength();
} catch (IOException e) {
return -1;
} finally {
conn.disconnect();
}
}

Android read remote text files exits with Unexpected End Of Stream

I'm downloading different medias files from my http server; mp3, jpg/png/ and html.
Everything worked fine when I used the now deprecated HttpClient.
I decided to use the HttpURLConnection.
But I encounter a problem with text files(html).
read() blocks on small html files, maybe waiting for a EOF or I don't know what, during few seconds and exits with the Exception "unexpected end of stream".
My code is:
URL url = new URL(urlString);
postParams = String.format("registration=%s&"....);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true); // It's a POST request which replies sending a file
urlConnection.setChunkedStreamingMode(0);
if (fileName.contains(".htm")) { // Tried this to see...
urlConnection.setRequestProperty("Accept-Charset", "UTF-8");
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + "UTF-8");
}
OutputStream output = urlConnection.getOutputStream();
output.write(postParams.getBytes("UTF-8"));
is = new BufferedInputStream(urlConnection.getInputStream());
/* Get information from the HttpURLConnection automatically fires the request
* http://stackoverflow.com/questions/2793150/using-java-net-urlconnection-to-fire-and-handle-http-requests
*/
int status = urlConnection.getResponseCode();
if (status == 200) {
int len, size = 0;
byte[] buf = new byte[128 * 1024];
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
try {
while ((len = is.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, len);
size += len;
}
os.flush();
} catch (IOException e) {
Log.d(Constants.APP_TAG, "IOException." + e); // HTML files end here after few seconds
} finally {
nbFilesDownloaded++;
is.close();
os.close();
file.setReadable(true, false);
file.setWritable(true, false);
}
}
Any idea to explain why it cannot normally exit from read()??
EDIT: I verified that for the html files which cause this exception, my webserver doesn't include Content-Length in the header. Can it be the cause of the problem?
Try to use okhttp http://square.github.io/okhttp/. I have downloaded the files correctly. I hope to help.
Paul.

Sending special characters (ë ä ï) in POST body with DataOutputStream in Android

Im currently working on an Android app with heavy server side communication. Yesterday I got a bug report saying that the users aren't able to send (simple) special characters such as ëäï.
I searched but didn't find anything helpful
Possible duplicate ( without answer ):
https://stackoverflow.com/questions/12388974/android-httpurlconnection-post-special-charactes-to-rest-clint-in-android
My relevant code:
public void execute(String method) {
HttpsURLConnection urlConnection = null;
try {
URL url = new URL(this.url);
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestMethod(method);
urlConnection.setReadTimeout(30 * 1000);
urlConnection.setDoInput(true);
if (secure)
urlConnection.setRequestProperty("Authorization", "Basic " + getCredentials());
if (body != null) {
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlConnection.setFixedLengthStreamingMode(body.length());
urlConnection.setDoOutput(true);
DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());
dos.writeBytes(body);
dos.flush();
dos.close();
}
responseCode = urlConnection.getResponseCode();
message = urlConnection.getResponseMessage();
InputStream in = null;
try {
in = new BufferedInputStream(urlConnection.getInputStream(), 2048);
} catch (Exception e) {
in = new BufferedInputStream(urlConnection.getErrorStream(), 2048);
}
if (in != null)
response = convertStreamToString(in);
} catch (UnknownHostException no_con) {
responseCode = 101;
}catch (ConnectException no_con_2){
responseCode = 101;
}catch(IOException io_ex){
if(io_ex.getMessage().contains("No authentication challenges found")){
responseCode = 401;
}else
responseCode = 101;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null)
urlConnection.disconnect();
}
}
body is a String ;-)
Hope we can solve this together
UPDATE:
Tried:
writeUTF()
need a server capable of understanding the modified UTF-8
byte[] buf = body.getBytes("UTF-8");
dos.write(buf, 0, buf.length);
strings work but no special chars
update: Got it working with StringEntity(* string, "UTF-8") then parse the result to a byte[] and write it with dos.write(byte[])!
--
Setting the encoding of the StringEntity did the trick for me:
StringEntity entity = new StringEntity(body, "UTF-8");
seen here: https://stackoverflow.com/a/5819465/570168
i am not totally sure buy try this utility for your case
URLEncoder.encode(string, "UTF-8")
I faced this problem in android while passing a json with special char (ñ).
In my WebApi method, [FromBody] param is giving null, it seems it can't parse the json.
I got it working by getting bytes as UTF-8 then writing it in DataOutputStream (Client-side fix).
byte[] b = jsonString.getBytes("UTF-8");
os.write(b, 0, b.length);

Timeout when downloading a string

I am using the following two functions to download a string from a server. I am also logging the time it takes to download the text, both as seen by the client and also as seen by the server. The downloaded string is never the same.
The server time is only few milliseconds but the time seen by the client is on average 100 milliseconds depending on the wifi signal. Occasionally the client time goes up to 3000 milliseconds (but never higher than 3200 ms) even though the server time is still within acceptable limits.
I'm starting to think that a timeout is somewhere defined but I don't know where it might be. It´s not in my code and I've looked around on the developer site and google without results.
I'm hoping that someone can give me some clues where this delay might be defined and confirm that it is 3000 ms by default.
private String DownloadText(String URL)
{
String str = "";
int BUFFER_SIZE = 2000;
InputStream in = null;
try{
in = OpenHttpConnection(URL);
} catch (IOException e1) {
e1.printStackTrace();
return "";
}
catch(ArithmeticException ae){
//
}
try{
InputStreamReader isr = new InputStreamReader(in);
int charRead;
char[] inputBuffer = new char[BUFFER_SIZE];
try {
while ((charRead = isr.read(inputBuffer))>0)
{
//---convert the chars to a String---
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
str += readString;
inputBuffer = new char[BUFFER_SIZE];
}
in.close();
} catch (IOException e) {
e.printStackTrace();
return "";
}
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
with
private InputStream OpenHttpConnection(String urlString) throws IOException {
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection)) throw new IOException("Not an HTTP connection");
try{
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
}
catch (Exception ex) {
throw new IOException("Error connecting");
}
return in;
}
BTW: I borrowed the two functions from one of google's search results.
EDIT: I am calling DownloadText(url) from within a thread. I was beginning to think that could have something to do with the timeout. Does it ?
This will help you:
private static final int CONNECT_TIMEOUT_MILL = 10000;
private static final int READ_TIMEOUT_MILL = 3000;
....
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(CONNECT_TIMEOUT_MILL);
con.setReadTimeout(READ_TIMEOUT_MILL);
....
I've seen similar behavior like this before. In my case it was in AJAX calls and it was a real head puzzler for me too. It turned out in my case that the server was returning the data without either
specifying the content length or
closing the http connection
So the browser had to wait for the connection to timeout before it would process the data and generate the receive event. Something similar might be happening in your case, so break out the network analysis software and verify the http correctness. I normally use Fiddler2 for this type of work, but I don't know if you can make the android device go through a proxy very well. It sounds like you control the web server, so maybe inspecting the tcp packets from that end is possible.

How to work with an image using url in android?

Given a Url for an image, I want to downoload it and paste it onto my canvas in android. How do I retrieve the image into my app ?
Please help.
Thanks,
de costo.
Dont forget to give the app the permission to connect to the Web,
in the AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
You can use the following code to download an image:
URLConnection connection = uri.toURL().openConnection();
connection.connect();
InputStream is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, 8 * 1024);
Bitmap bmp = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
Requires the following permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
There is a an HTTP client library that might be supported in Android now, but for any fine grain control you can use URL & HttpURLConnection. the code will look something like this:
URL connectURL = new URL(<your URL goes here>);
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
// do some setup
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("GET");
// connect and flush the request out
conn.connect();
conn.getOutputStream().flush();
// now fetch the results
String response = getResponse(conn);
where getResponse() looks something like this, in your case you are getting
a pile of binary data back you might want to change the StringBuffer to a byte array
and chunk the reads by a larger increment.
private String getResponseOrig(HttpURLConnection conn)
{
InputStream is = null;
try
{
is = conn.getInputStream();
// scoop up the reply from the server
int ch;
StringBuffer sb = new StringBuffer();
while( ( ch = is.read() ) != -1 ) {
sb.append( (char)ch );
}
return sb.toString();
}
catch(Exception e)
{
Log.e(TAG, "biffed it getting HTTPResponse");
}
finally
{
try {
if (is != null)
is.close();
} catch (Exception e) {}
}
return "";
}
As you are talking about image data which can be large, other things you need to be assiduous about in Android is making sure you release your memory as soon as you can, you've only got 16mb of heap to play with for all apps and it runs out fast and the GC will drive you nuts if you aren't really good about giving back memory resources

Categories

Resources