Android HttpUrlConnection WiFi / GSM блок переключателей - PullRequest
0 голосов
/ 11 августа 2011

Я отчаянно пытаюсь найти решение для подключения к WiFi / GSM при загрузке файлов через HttpUrlConnection. Я видел людей, борющихся с подобными проблемами, но все еще не мог найти рабочее решение. Вот код:

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 */
}

Проблема в том, что всякий раз, когда я переключаюсь с WiFi на GSM или с GSM на WiFi во время цикла загрузки, поток останавливается на линии, отмеченной в коде: output_byte.write (buffer, 0, bufferSize);

Я пытался использовать connection.disconnect () , который должен выдавать какое-то IOException (это происходит в обычных ситуациях, но не в данном конкретном случае)

Я пытался использовать OutputStream.close () , вызываемый из второго потока, но также зависает второй (основной интерфейс) поток, что не позволяет мне даже закрыть приложение.

Я искал что-то вроде connection.isAvailable () , которое я мог бы вызвать до ouptut_byte.write, но не смог найти ничего полезного в классе HttpUrlConnection.

Я пытался отслеживать состояние Wi-Fi, но поток загрузки, кажется, быстрее, чем изменение состояния Wi-Fi, и он блокируется, прежде чем я могу предоставить текущее изменение состояния Wi-Fi. (также попробовал ConnectivityManager - без разницы)

Наконец, я попытался убить поток, добавив флаг volatile в переменную Thread и используя Thread.interrupt () - безрезультатно. Нить все еще жива и находится в состоянии «РАБОТАЕТ».

У вас есть идеи, как я могу решить проблему? Я был бы очень рад, если бы я мог поймать любой тип исключения в этой теме после блоков is.

Ответы [ 4 ]

2 голосов
/ 14 декабря 2012

Я попал в ту же ситуацию, что и Шаар.У меня есть приложение для загрузки файла на сервер.На HTC Desire A8181 (Android 2.2.2), когда я отключаю мобильное соединение для передачи данных (или переключаю его в соединение Wi-Fi), когда appliction записывает в выходной поток (я записываю туда блоки данных 512 кБ), оно просто блокируется там дляпримерно 16 минут.После этих 16 минут я получаю Socket Exception (что не всегда одно и то же).

Когда я пробую его на другом устройстве или на том же устройстве (HTC Desire A8181), но при подключении по Wi-Fi, исключение составляетвыбрасывается сразу после закрытия соединения. Так что я думаю, что это ошибка. И одним из решений, о котором я думаю, является загрузка в поток, а когда происходит изменение соединения (BroadcastReceiver), то пусть поток умирает (в течение этих 16 минут) и начать другую тему.Это не очень хорошее решение из-за живых потоков в системе, но я не знаю другого решения ...

Пример кода такой же, как и в начале этого потока.Я также попробовал и Apache HttpClient и HttpUrlConnection.

0 голосов
/ 11 августа 2011

Спасибо тебе, Феми, за твой ответ!

Я попробовал это решение сегодня, и это не имеет никакого значения.Я использовал пользовательскую множественность http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/, найденную здесь, смешанную с некоторыми библиотеками apache: httpclient, httpcore и httpmime

Вот новый код:

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)); 

По-прежнему без эффектов ...

Также пытались использовать httpPost.abort() и httpClient.getConnectionManager().closeExpiredConnections() и httpClient.getConnectionManager().shutdown().
Никаких эффектов вообще, поток не выдает никаких исключений, он остается в состоянии RUNNINGно он заблокирован и мертв.

Я думаю, что мы ничего не можем с этим поделать.

Странно то, что когда я включаю Wi-Fi обратно в потоке "просыпается" и продолжаюзагрузка, но это бессмысленно, если мне придется вернуться в зону Wi-Fi для завершения процесса загрузки.

PS. Оба примера были протестированы на 3 реальных устройствах: Samsung Spica под управлением 2.1Samsung Galaxy S под управлением 2.2.1 и Motorola Defu под управлением 2.2.1.В то время как у Motorola и Spica возникают проблемы с описанной ситуацией, Galaxy S ведет себя по-разному - он генерирует IOException, чего я и ожидал от других.

0 голосов
/ 27 сентября 2012

Поздний ответ, но я использовал следующие вопросы и ответы Android: как обрабатывать изменения в сети (от GPRS до Wi-Fi и наоборот) при опросе данных , чтобы справиться с этим.Загрузите его в свой собственный поток и при сбое в сети, перезапустите поток и загрузите.

0 голосов
/ 11 августа 2011

Вам может понадобиться использовать HttpClient: существуют методы для установки времени ожидания сокета , которое может делать то, что вы хотите, что в действительности завершает соединение и выдает какое-то исключение при разрыве сетевого соединенияпо выключателю.

...