In my application I am sending multiple http requests.
Since, the network may go down at any time. So, before sending each request should I use android ConnectionManager to check the network state? I am feeling that some other better way would be there to handler this.(Rather than using the android connection manager service each time when multiple request are sent on each fragment)
Take a look at this question. If you want to avoid use of the ConnectionManager, you could use a try-catch block and check for an exception while trying to make a connection (provided you are using the java.net.* library to do the HTTP requests). For example, something like this was used in that question:
URL url = ...
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setReadTimeout(15000);
try {
InputStream in = new BufferedInputStream(c.getInputStream());
httpResult = readStream(in);
} catch (IOException e) {
// Here is where an exception would be thrown if there is no internet.
// Would likely actually be an UnknownHostException
Log.e(TAG, "Error: ", e);
} finally {
c.disconnect();
}
Related
I'm trying to send a PUT request but failing bad in it.
Only the first time I'm trying to send data the following line follows up in the log (in further use no exceptions are thrown):
E/DataScheduler: isDataSchedulerEnabled():false
I tried to google out what could that possibly mean, but with no luck. And even that in the further attempts on sending data the mentioned exception wont raise anymore, still no data is being sent. I'm trying to send it on my own server and I can see no connections are received on that side. Using my Android's browser I can send a successful GET request however.
I've also set the permission for Internet already by:
<uses-permission android:name="android.permission.INTERNET" />
I'm not very familiar with Java or Android but as far as I know the request should be formed and sent the following way:
public void sendFilesWithPut(String address, String file) {
new AsyncTask<String,Void,Void>() {
#Override
protected Void doInBackground(String... params) {
try {
//Log.d("HTTP:","Address:"+params[0]+":"+params[1]+" file:"+params[2]);
URL url = new URL("http://" + params[0] + ":" + params[1]);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());
out.write(params[2]);
out.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute(address, Integer.toString(port), file);
}
I can print a line to Log every time I attempt to send a PUT request and it's all correct: IP, port and the to-be-sent-String.
Any ideas how to make it work?
I suspect that params[0] and params[1] are actually the address and port for your url. If so then you may wish to refer to the following post:
Making PUT request with JSON data using HttpURLConnection is not working
Where the content will be sent if you start interaction with the response, so add the following:
System.err.println(httpCon.getResponseCode());
as per the post, and see if that works?
Ok, what I want is to ask to my server for an url, and load that url on a WebView, but a problem appears: when you run a http request you need to do it in a separate thread, and loadUrl() needs to be runned in the UI thread. So, how can I do to first make the request and then load the url?
The code isn't inside an Activity, so I can't call runOnUiThread(Runnable).
How can I do it?
EDIT: As Alécio suggested, it's better to not have too much code inside custom views, so what I want to do is to create a method that allows me to pass the url when the app has received the response from the server. The code that I'm using for the request is:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://requesturl.com");
try {
HttpResponse response = client.execute(post);
InputStream content = response.getEntity().getContent();
String url = getStringFromInputStream(content);
//web.loadUrl(url);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
So, it's possible to know when a response has been received?
WebView is a UI component it must be in the context of an Activity or Fragment, so loadUrl() from the UI thread is OK.
If you want to make a server call, process the response before displaying something on the UI, then you might just use the conventional options to connect to a server URL using the HttpURLConnection. See the sample code below:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
In this example, you really need to execute it in a background Thread. Never from the UI Thread.
Google is providing 2 different examples of HttpURLConnection usage.
Calling InputStream's close
http://developer.android.com/training/basics/network-ops/connecting.html
// Given a URL, establishes an HttpUrlConnection and retrieves
// the web page content as a InputStream, which it returns as
// a string.
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
// Only display the first 500 characters of the retrieved
// web page content.
int len = 500;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.d(DEBUG_TAG, "The response is: " + response);
is = conn.getInputStream();
// Convert the InputStream into a string
String contentAsString = readIt(is, len);
return contentAsString;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
Calling HttpURLConnection's disconnect
http://developer.android.com/reference/java/net/HttpURLConnection.html
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
For resource leakage and performance consideration (Need not to setup network connection from ground up, as my app will communicate with same server most of the time), should we
Call HttpURLConnection's disconnect only.
Call the InputStream's close only.
Call both HttpURLConnection's disconnect & InputStream's close (Haven't seen such official example so far).
According to Oracle's Java, calling the disconnect() may close the underlying socket connection, if the connection is idle (not fetching anything). This "indicates that other requests to the server are unlikely in the near future" using that same HttpUrlConnection instance. You will have to reopen a new socket connection by creating another HttpUrlConnection.
However, Google has modified HttpUrlConnection so that socket connections can be reused. In Android, the underlying Socket used by a HttpUrlConnection may be persisted and reused for multiple requests. If you call disconnect after completing your request, it may send the socket to a pool containing other idle connections, ready to be reused. The system does this to reduce latency.
From the documentation:
Unlike other Java implementations, this will not necessarily close
socket connections that can be reused. You can disable all connection
reuse by setting the http.keepAlive system property to false before
issuing any HTTP requests.
So you should call disconnect to release resources (streams and sockets), but some of the resources released may be reused (i.e. the socket will go into a pool of idle sockets, ready for the next HttpUrlConnection instance to reuse it).
As for why the first example did not call disconnect(), that is the Java SE way of reusing the connection (I think, it's been a while). What the author did was manually close the InputStream of the connection and left the socket open and idle for reuse. The second example shows the correct way on Android.
In summary: calling disconnect() on Android will close any InputStream or OutputStream used for the connection and may send the socket used for the connection to a pool, ready to be reused for other requests. So, if you call disconnect(), there is no need to call InputStream#close().
Both close and disconnect method release the connection if not yet released with following 2 differences:
close method throws IOException. Hence in first example, the enclosing method downloadUrl's signature has throws IOException. Where as disconnect method does not throw any exception.
Calling close method ensures that any future references made to the closed connection such as read operation, will result in IOException.
The most important design fact about Android's HttpURLConnection implementation is :
Connection is held when the last byte of the response is consumed.
When the response if fully read, the connection is released and will
be pooled immediatetly.
You can see in the below image, variable connection & connectionReleased are set to null and true respectively, as soon as all data is read. In this case calling disconnect makes no difference, calling close just ensures future calls on closed connection throws IOException.
If data is still available on the InputStream, close or disconnect has to be called to release the connection explicitly. In this case the connection is not reused and underlying socket connection is also closed. This is done in anticipation that more data may arrive on the InputStream.
You can see in below code snippets, both disconnect and close will finally invoke httpEngine.release(false), which will close the connection without adding to the connection pool.
disconnect implementation:
#Override public final void disconnect() {
// Calling disconnect() before a connection exists should have no effect.
if (httpEngine != null) {
httpEngine.release(false);
}
}
close implementation:
#Override public void close() throws IOException {
if (closed) {
return;
}
closed = true;
if (bytesRemaining != 0) {
unexpectedEndOfInput();
}
}
unexpectedEndOfInput implementation:
protected final void unexpectedEndOfInput() {
if (cacheRequest != null) {
cacheRequest.abort();
}
httpEngine.release(false);
}
release implementation:
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
Summary :
Connection is automatically released to the connection pool as soon as the last byte of the response is consumed.
If the IOException will be handled by method operating on InputStream, use disconnect. If the IOException will be handled by the caller of the method operating on InputStream, use close. Remember close ensures IOException is thrown when read operation is performed on closed connection in future.
Here's the question in simplest way.
I create a HTTPS connection to my server through proxy using HttpUrlConnection Object.
My proxy closes the connection but my code still tries to reuse the same connection. And so I get EOFException.
How do I handle such cases?
I'd recommend disabling the http.keepalive system property. The performance section of the documentation indicates that socket connections will be reused when possible. It sounds like it is trying to reuse the connection, but the proxy has already closed it. On this post, Darrell also indicates that changing the system property solved his problem.
System.setProperty("http.keepAlive", "false");
Turns out they've fixed this issue in Android on Jan 8th [1]. The fix basically marks the old connection as recycled and internally retries the request.
To fix this for now, I would suggest retrying requests if an EOFException is encountered with a retry limit to prevent stackoverlows.
https://android.googlesource.com/platform/libcore/+/19aa40c81c48ff98ccc7272f2a3c41479b806376
I had this problem with normal HTTP connections as well. The first request went OK, the second failed with an EOFException.
Eventuelly I fixed it by removing...
urlConnection.setChunkedStreamingMode(0);
...from the HttpUrlConnection.
I could be that the webserver I'm calling can't handle chuncked data well. Don't know.
If you don't want to reuse the connection then release it.
finally {
urlConnection.disconnect();
}
You can use this method to pick data from server then you convert the inputs trim to string then you can parse for further use.`
public static InputStream getUrlData(final String url)
throws URISyntaxException, ClientProtocolException, IOException {
final DefaultHttpClient client = new DefaultHttpClient();
final HttpGet method = new HttpGet(new URI(url));
final HttpResponse res = client.execute(method);
return res.getEntity().getContent();
}
Maybe httpClient "has more bugs" and is deprecated, but this problem with JellyBean is a showstopper. I am using Ksoap2 so I tried all the suggested answers that I could.
System.setProperty("http.keepAlive", "false");
httpTransportSE.getServiceConnection().setRequestProperty("Connection", "close");
httpTransportSE.getServiceConnection().disconnect();
Nothing worked - my solution was to rollback the version of Ksoap2 I'm using from 3.1.1 to 2.6.5. Using 2.6.5 the problem is substantially reduced. Still testing but maybe even solved.
I found that retrying the connection fixes the issue as seen here: https://stackoverflow.com/a/20302767/2520390
Make sure you close off the connection before your recursive call.
Also, I added the following to the connection to close the connection, though I'm not sure if it helps:
if (retries > 0) {
connection.setRequestProperty("Connection", "close");
}
You shouldn't be attempting to reuse the same HttpURLConnection instance. The docs in the very bottom line of the "Class Overview" say
Each instance of HttpURLConnection may be used for one
request/response pair.
Keep-Alive connections work at a different level, see the disconnect docs:
http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()
Unlike other Java implementations, this will not necessarily close
socket connections that can be reused. You can disable all connection
reuse by setting the http.keepAlive system property to false before
issuing any HTTP requests.
So you should always use a fresh HttpURLConnection and let the socket pool handle re-use.
There were apparently bugs with keep-alive connections pre-Froyo (2.2) so it is recommended to disable keep-alive on those old devices.
In my case the EOFException was caused by my server not sending a full response, see the details here: https://stackoverflow.com/a/27845172/2335025
You shouldn't be attempting to reuse the same HttpURLConnection instance. The docs in the very bottom line of the "Class Overview" say
Each instance of HttpURLConnection may be used for one
request/response pair.
Keep-Alive connections work at a different level, see the disconnect docs:
http://developer.android.com/reference/java/net/HttpURLConnection.html#disconnect()
Unlike other Java implementations, this will not necessarily close
socket connections that can be reused. You can disable all connection
reuse by setting the http.keepAlive system property to false before
issuing any HTTP requests.
So you should always use a fresh HttpURLConnection and let the socket pool handle re-use. There are perhaps issues if it tries to reuse a socket that has been closed by the server, which the answers to this question deal with: Android HttpUrlConnection EOFException
There were apparently bugs with keep-alive connections pre-Froyo (2.2) so it is recommended to disable keep-alive on those old devices.
In my case the EOFException was caused by my server not sending a full response, see the details here: https://stackoverflow.com/a/27845939/2335025
if (Build.VERSION.SDK != null
&& Build.VERSION.SDK_INT > 13) {
con.setRequestProperty("Connection", "close");
}
Try this code:`
Httppost method:
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_MILLISEC);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_MILLISEC);
HttpClient client = new DefaultHttpClient(httpParams);
HttpPost request = new HttpPost("put_url");
request.setHeader("Content-Type", "application/xml");
String file = resourceXml();
StringEntity se = null;
try {
se = new StringEntity(file);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
se.setContentEncoding("UTF-8");
se.setContentType("application/xml");
request.setEntity(se);
HttpResponse response = null;
try {
response = client.execute(request);
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
HttpEntity entity = response.getEntity();
InputStream is = null;
try {
is = entity.getContent();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String _response = convertStreamToString(is);
Log.i(TAG, "Response:" + _response);
// Check if server response is valid code
int res_code = response.getStatusLine().getStatusCode();
Log.i(TAG, "status_code" + res_code);
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
`
to convert stream to string:`
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is),
8192);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append((line + "\n"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}`
I need to send a JSON request similar to jQuery's ajax method.
The official documentation quote on the data parameter says:
If value is an Array, jQuery serializes multiple values with same key based on the value of the traditional setting
So I have the same situation - a key that maps to an array "parameters":[123123, {"category":"123"}]
The complete data parameter looks like
$.ajax({
url: "/api/",
data: {"parameters":[123123, {"category":"123"}], "anotherParameter":"anotherValue"}
Would you mind telling how to achieve the same functionality in Java ?
UPD:
I've made it to work with the use of gson + collections + post request.
Here're some guide lines:
Sending POST requests in JAVA.
You might also want to consider performance issues related to different kinds of json parsers
What have you tried so far and what exactly is the problem? Is it that you don't know how to create a connection, that you don't know how to serialize your objects or that you don't know how to make the thing run asynchronously?
I don't think Java has any asynchronous HTTP call methods, you need to use a regular URLConnection and run it in a separate thread. The connection itself is formed like this:
URL url = null;
URLConnection urlConnection = null;
String myURL = "http://example.com/ajax.php?foo=bar";
try {
url = new URL(myURL);
urlConnection = url.openConnection();
} catch (Exception e) {
e.printStackTrace();
return;
}
InputStream responseStream = null;
try {
responseStream = urlConnection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
return;
}
Then you must use something like the AsyncTask class to make it a background job.
For converting your objects to JSON you might want to use the GSON library.