Android HttpUrlConnection WiFi/GSM switch block
I am desperatly trying to find a soulution for WiFi/GSM connection switch while uploading files via HttpUrlConnection. I have seen people struggling with similar problems but still couldn't find a working solution. Here is the code:
try {
/* Opening file stream and so... */
URL url = new URL(url_to_send);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// connection.setConnectTimeout(1000); // doesn't have any effect
// connection.setReadTimeout(1000);
connection.setChunkedStreamingMode(maxBufferSize);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data; charset=utf-8; boundary=" + BOUNDARY);
bytesAvailable = file_input.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = file_input.read(buffer, 0, bufferSize);
already_send += bytesRead;
while (bytesRead > 0) {
/* Updating some progressbar values */
/* HERE IS THE LINE WHERE THREAD HANGS */
output_byte.write(buffer, 0, bufferSize);
bytesAvailable = file_input.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = file_input.read(buffer, 0, bufferSize);
already_send += bytesRead;
}
output_byte.writeBytes(endBoundary);
output_byte.flush();
// Responses from the server (code and message)
serverResponseCode = connection.getResponseCode();
serverResponseMessage = connection.getResponseMessage();
} catch (FileNotFoundException e) {
Log.e(TAG, "Uploaded file not found");
e.printStackTrace();
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed URL");
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, "Uploading problem: " + e.toString());
e.printStackTrace();
} finally {
/* closing connection & streams */
}
The problem is that whenever i switch from WiFi to GSM or from GSM to WiFi during the uploading loop the Thread freezes on the line marked in the code: output_byte.write(buffer, 开发者_如何转开发0, bufferSize);
I have tried using connection.disconnect() which should throw some kind of a IOException (it does in normal situations but not in this particular case)
I have tried using OutputStream.close() called from second thread but it also hangs the second (main UI) thread making me unable to even close the app.
I have been searching for something like connection.isAvailable() which I could call before the ouptut_byte.write but I couldn't find anything useful in HttpUrlConnection class.
I have tried monitoring the WiFi state but the uploading thread seems to be faster than wifi state change and it blocks before I am able to provide it the current wifi state change. (also tried the ConnectivityManager - no difference)
Finally I have tried to kill the thread by adding volatile flag to my Thread variable and using Thread.interrupt() - no effect. Thread is still alive and it's state is "RUNNING".
Have you got any ideas how Can I solve the problem? I would be really glad if I could catch any type of exception in this thread after is blocks.
I got into exactly the same situation as Shaar did. I have an application for the file upload on the server. On the HTC Desire A8181 (Android 2.2.2) when I turn off the mobile data connection (or switch it into wifi connection) when the appliaction writes into output stream (I am writing there 512 kB data blocks) it just blocks in there for approximately 16 minutes. After these 16 minutes I get an Socket Exception
(which is not always the same).
When I try it on other device or on the same device (HTC Desire A8181) but on wifi connection, the exception is thrown right after the connection is closed. So I think it is a bug. And one solution that I think about is to upload in a Thread and when there is a change in connection (BroadcastReceiver
) then let the thread die (for these 16 minutes) and start another Thread. It is not a nice solution because of living threads in the system but I don't know any other solution...
The example code is the same as in the beginning of this thread. I also tried both the Apache's HttpClient
and the HttpUrlConnection
.
You might need to use HttpClient: there are methods to set the socket timeout that may do what you want, which is in effect ending the connection and throwing some kind of exception when the network connection is broken by the switch.
Late response, but I used the following Q&A Android, How to handle change in network (from GPRS to Wi-fi and vice-versa) while polling for data to handle this. Have the upload in its own thread and on a network failover, restart the thread and upload.
Thank you Femi for your answer!
I've tried that solution today and it makes no difference at all. I have used a custom multipartentity http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/ found in here mixed with some apache libraries: httpclient, httpcore and httpmime
Here is the new code:
File uploaded_file = new File(mess.getPath());
CustomMultiPartEntity multipart = new CustomMultiPartEntity(new CustomMultiPartEntity.ProgressListener() {
@
Override
public void transferred(long num) {
Log.v(TAG, num * 100 / total_size + " !");
// updating progressbar
}
});
// adding some fields to multipart
multipart.addPart(file_field, new FileBody(uploaded_file));
total_size = multipart.getContentLength();
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setSoTimeout(params, 5000);
HttpConnectionParams.setConnectionTimeout(params, 5000);
httpClient = new DefaultHttpClient(params);
httpContext = new BasicHttpContext();
httpPost = new HttpPost(url_to_send);
httpClient.getParams().setParameter("http.protocol.content-charset", "UTF-8");
httpPost.setEntity(multipart);
// Responses from the server (code and message)
HttpResponse response = httpClient.execute(httpPost);
serverResponseCode = response.getStatusLine().getStatusCode();
serverResponseMessage = response.getStatusLine().getReasonPhrase();
After WiFi / GSM
switch the Thread acts the same blocking the execution.I have also tried setting the timeouts this way:
httpclient.getParams().setParameter("http.socket.timeout", new Integer(1000));
httppost.getParams().setParameter("http.socket.timeout", new Integer(5000));
Still no effects...
Also tried using httpPost.abort()
and httpClient.getConnectionManager().closeExpiredConnections()
and httpClient.getConnectionManager().shutdown()
.
No effect at all, thread is not throwing any exceptions, it remains in state RUNNING but it is blocked and dead.
I think that there is nothing we can do about it.
Strange thing is that when I turn the wifi back on the thread "wakes up" and continue uploading but it is pointless if I would have to get back to wifi area in order to complete the uploading process.
PS. Both examples were tested on 3 real devices: Samsung Spica runing 2.1, Samsung Galaxy S running 2.2.1 and Motorola Defu runing also 2.2.1. While Motorola and Spica are having problems with the described situation the Galaxy S behaves differently - it throws an IOException which is something that I would expect from the other ones.
精彩评论