Can I set a time out for BufferReader? - android

The first time I made a method to read data from my chat server, it frooz. I found out I had the wrong port number and it was freezing at
new BufferedReader(new InputStreamReader(conn.getInputStream()));
Is there a way to have a time out so my program does not freez on a network error? I'm assuming there must be,
the complete methed
void SendMessage()
{
try {
URL url = new URL("http://50.63.66.138:1044/update");
System.out.println("make connection");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// String line;
String f=new String("");
String line=new String();
while ((line= rd.readLine() ) != null) {
f=f+line;
f+="\n";
}
mUsers.setText(f);
} catch (Exception e) {
System.out.println("exception");
System.out.println(e.getMessage());
}
}
}

First of all, I hope you execute this code in a separate thread in order to make your UI thread responsive on touches even while connection is being established.
Second, there are two timeout methods available for URLConnection class:
http://developer.android.com/reference/java/net/URLConnection.html#setReadTimeout(int)
http://developer.android.com/reference/java/net/URLConnection.html#setConnectTimeout(int)
Try to play with these guys, maybe it will help.
If not, you can always do your own way:
start the thread with a runnable which tries to establish a connection and InputReader. Then wait for some time-out and try to interrupt the thread if it is still running.

Related

Android App crashes but the code shows no error

Okay so I'm trying to make an app that is able to retrieve data from a web server and then show it on a textView and constantly update it if the data changes from the web server. And what I got so far after many rounds of trying is this as shown
public class HttpTest extends AppCompatActivity {
TextView text = (TextView) this.findViewById(R.id.textView3);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_http_test);
HttpURLConnection urlConnection = null;
try {
URL url = new URL("http://IPGOESHERE/");
HttpURLConnection urLConnection = (HttpURLConnection) url.openConnection();
InputStream in = urLConnection.getInputStream();
BufferedReader data = new BufferedReader(new InputStreamReader(in));
StringBuilder total = new StringBuilder();
String line;
while ((line = data.readLine()) != null) {
total.append(line).append('\n');
}
String result = total.toString();
text.setText(result);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
I don't think what i have written allows for constant update, but I at least want to be able to show some kind of data on a textView and make sure it doesn't crash first. So if someone could point out what I'm doing wrong it will be much appreciated.
The app crash because you are making HTTP request on main thread. Use an AsyncTask instead
you need to this kind of work on a different thread. try using an AsyncTask.
you create a class that extends AsyncTask, than make the url connection in the doInBackground method (a method that gets called on a worker thread). you can then update the textview in the onPostExecute method which is called on the ui thread. good luck :)

API call far faster on iOs and browser than on android

I have a trouble with my HttpsConnection on android.
First of all, no it is not a duplicate. I try almost all the solutions on SO, like changing the keep-alive option or the timeout ( and some of them indeed optimized a part of my code a little bit ) but it is still 5 to 10 times ( probably more ) slower on android than on iOS.
Sending a request to my server takes several seconds on android while it's almost instant on iOS and from a browser. I am sure that the server is not in cause. But it seems that getting the inputstream is terribly slow!
This line:
in=conn.getInputStream();
is the most delaying one, taking several seconds by itself.
My aim is to get a JSON from my server. My code is supposed to be technically as optimized as possible ( and it can probably help some people with HttpsConnection on the same time ):
protected String getContentUrl(String apiURL)
{
StringBuilder builder = new StringBuilder();
String line=null;
String result="";
HttpsURLConnection conn= null;
InputStream in= null;
try {
URL url;
// get URL content
url = new URL(apiURL);
System.setProperty("http.keepAlive", "false");
trustAllHosts();
conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(DO_NOT_VERIFY);
conn.setRequestMethod("GET");
conn.setRequestProperty(MainActivity.API_TOKEN, MainActivity.ENCRYPTED_TOKEN);
conn.setRequestProperty("Connection", "close");
conn.setConnectTimeout(1000);
in=conn.getInputStream();
// open the stream and put it into BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((line=br.readLine())!= null) {
builder.append(line);
}
result=builder.toString();
//System.out.print(result);
br.close();
} catch (MalformedURLException e) {
result=null;
} catch (IOException e) {
result=null;
} catch (Exception e) {
result=null;
}
finally {
try {
in.close();
}catch(Exception e){}
try {
conn.disconnect();
}catch(Exception e){}
return result;
}
}
However, it keeps taking several seconds.
So I would like to know: is there a way to improve the speed of this API call? The problem is not the server or the JSON parsing but for sure the function above. Thanks a lot.

Android - How can I open a persistent HTTP connection that receives chunked responses?

I'm trying to establish a persistent HTTP connection to an API endpoint that publishes chunked JSON responses as new events occur. I would like to provide a callback that is called each time the server sends a new chunk of data, and keep the connection open indefinitely. As far as I can tell, neither HttpClient nor HttpUrlConnection provide this functionality.
Is there a way to accomplish this without using a TCP socket?
One solution would be to use a delimeter such as \n\n to separate each json event. You could remove blank lines from original json before sending. Calling setChunkedStreamingMode(0) allows you to read content as it comes in (rather than after the entire request has been buffered). Then you can simply go through each line, storing them, until a blank line is reached, then parse the stored lines as JSON.
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setChunkedStreamingMode(0);
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sBuffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
if (line.length() == 0) {
processJsonEvent(sBuffer.toString());
sBuffer.delete(0, sBuffer.length());
} else {
sBuffer.append(line);
sBuffer.append("\n");
}
}
As far as I can tell, Android's HttpURLConnection doesn't support receiving chunks of data across a persistent HTTP connection; it instead waits for the response to fully complete.
Using HttpClient, however, works:
HttpClient httpClient = new DefaultHttpClient();
try {
HttpUriRequest request = new HttpGet(new URI("https://www.yourStreamingUrlHere.com"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
try {
HttpResponse response = httpClient.execute(request);
InputStream responseStream = response.getEntity().getContent();
BufferedReader rd = new BufferedReader(new InputStreamReader(responseStream));
String line;
do {
line = rd.readLine();
// handle new line of data here
} while (!line.isEmpty());
// reaching here means the server closed the connection
} catch (Exception e) {
// connection attempt failed or connection timed out
}

Do I need to call HttpURLConnection.disconnect after finish using it

The following code basically works as expected. However, to be paranoid, I was wondering, to avoid resource leakage,
Do I need to call HttpURLConnection.disconnect, after finish its usage?
Do I need to call InputStream.close?
Do I need to call InputStreamReader.close?
Do I need to have the following 2 line of code : httpUrlConnection.setDoInput(true) and httpUrlConnection.setDoOutput(false), just after the construction of httpUrlConnection?
The reason I ask so, is most of the examples I saw do not do such cleanup. http://www.exampledepot.com/egs/java.net/post.html and http://www.vogella.com/articles/AndroidNetworking/article.html. I just want to make sure those examples are correct as well.
public static String getResponseBodyAsString(String request) {
BufferedReader bufferedReader = null;
try {
URL url = new URL(request);
HttpURLConnection httpUrlConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = httpUrlConnection.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
int charRead = 0;
char[] buffer = new char[1024];
StringBuffer stringBuffer = new StringBuffer();
while ((charRead = bufferedReader.read(buffer)) > 0) {
stringBuffer.append(buffer, 0, charRead);
}
return stringBuffer.toString();
} catch (MalformedURLException e) {
Log.e(TAG, "", e);
} catch (IOException e) {
Log.e(TAG, "", e);
} finally {
close(bufferedReader);
}
return null;
}
private static void close(Reader reader) {
if (reader != null) {
try {
reader.close();
} catch (IOException exp) {
Log.e(TAG, "", exp);
}
}
}
Yes you need to close the inputstream first and close httpconnection next. As per javadoc.
Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
Next two questions answer depends on purpose of your connection. Read this link for more details.
I believe the requirement for calling setDoInput() or setDoOutput() is to make sure they are called before anything is written to or read from a stream on the connection. Beyond that, I'm not sure it matters when those methods are called.

Android: BluetoothSocket readLine timeout

I should insert a timeout on a readLine for a bluetooth input stream.
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
.getRemoteDevice("00:00:00:00:00:00");
sock = device.createInsecureRfcommSocketToServiceRecord(UUID
.fromString(insecureUUID));
sock.connect();
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line = in.readLine(); //if no answer from device..i'll wait here forever
do { [...]
} while ((line = in.readLine()) != null);
The connection works fine, but i've got a bluetooth serial converter linked to another device. If the second one is turned off i'll wait forever on the readLine. Any chance i can throw an exception or a timeout?
Thanks!!
I had the same problem and i solved it by creating a ResponderThread that extends Thread. This thread waits a certain amount of time and after that it checks if the input stream variable have changed.
try {
bufferedReader = new BufferedReader(new InputStreamReader(
bluetoothSocket.getInputStream()));
responderThread = new ResponderThread(bluetoothSocket, ACCESS_RESPONSE);
responderThread.start();
response= bufferedReader.read();
} catch (IOException ioe) {
// Handle the exception.
}
In my case the responderThread closes the socket if there is no response within 3 seconds and the execution goes into the catch block of the class where i create the responderThread. Then the exception is handled.

Categories

Resources