2 votes

Gestion des modifications du réseau lors du téléchargement de contenu

L'application sur laquelle je travaille est compatible avec Android 2.3 et plus. Comme le gestionnaire de téléchargement ne supporte pas https dans 2.3 (je ne comprends pas pourquoi), je suis en train d'implémenter ma propre version.

Le problème que j'ai est que si Android change de réseau (wifi à 3g etc) lors du téléchargement du contenu, j'obtiens l'erreur suivante.

06-14 17:26:48.770: W/System.err(15648): javax.net.ssl.SSLException: Read error: ssl=0x270420: I/O error during system call, Connection timed out
06-14 17:26:48.770: W/System.err(15648):    at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_read(Native Method)
06-14 17:26:48.770: W/System.err(15648):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:788)
06-14 17:26:48.770: W/System.err(15648):    at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
06-14 17:26:48.770: W/System.err(15648):    at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:134)
06-14 17:26:48.770: W/System.err(15648):    at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:174)
06-14 17:26:48.770: W/System.err(15648):    at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:188)
06-14 17:26:48.770: W/System.err(15648):    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:178)
06-14 17:26:48.770: W/System.err(15648):    at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:140)
06-14 17:26:48.770: W/System.err(15648):    at java.io.BufferedInputStream.read(BufferedInputStream.java:324)
06-14 17:26:48.770: W/System.err(15648):    at java.io.FilterInputStream.read(FilterInputStream.java:133)
06-14 17:26:48.770: W/System.err(15648):    at net.doo.download.ManualDocDownloader$AsyncDocDownloader.doInBackground(ManualDocDownloader.java:126)
06-14 17:26:48.770: W/System.err(15648):    at net.doo.download.ManualDocDownloader$AsyncDocDownloader.doInBackground(ManualDocDownloader.java:86)
06-14 17:26:48.770: W/System.err(15648):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
06-14 17:26:48.770: W/System.err(15648):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
06-14 17:26:48.780: W/System.err(15648):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
06-14 17:26:48.780: W/System.err(15648):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
06-14 17:26:48.840: W/System.err(15648):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
06-14 17:26:48.845: W/System.err(15648):    at java.lang.Thread.run(Thread.java:1019)

Le code qui pose problème ressemble à ceci...

public class AsyncDocDownloader extends AsyncTask<String, Integer, Boolean> {

        private int id;
        private Notification notification;

        public AsyncDocDownloader(int id, Notification notification) {
            this.id = id;
            this.notification = notification;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {

            notification.contentView.setProgressBar(R.id.status_progress, 100, values[0], false);

            notificationManager.notify(id, notification);
        }

        @Override
        protected Boolean doInBackground(String... values) {
            try {
                HttpGet get = new HttpGet(values[0]);
                HttpResponse resp = httpClientProvider.get().execute(get, context);
                    File dooDirectory = directoryProvider.get();
                    File fileName = new File(dooDirectory, values[1]);
                    InputStream input = new BufferedInputStream(resp.getEntity().getContent());
                    OutputStream output = new FileOutputStream(fileName);

                    int fileLength = Integer.valueOf(resp.getHeaders("Content-Length")[0].getValue());
                    int step = fileLength/20;
                    int counter = 0;
                    int progress = 0;

                    byte data[] = new byte[1024];
                    long total = 0;
                    int count;

                    while ((count = input.read(data)) != -1) {
                        total += count;
                        if(total > counter){
                            progress = progress + 5;
                            publishProgress(progress);
                            counter = step + counter;
                        }
                        output.write(data, 0, count);
                    }

                    output.close();
                    input.close();
                Log.d("DownloadDoc", "Completed download");
                return true;
            } catch (IOException e) {
                Log.d("DownloadDoc", "IOException");
                e.printStackTrace();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean success) {
            Log.d("DownloadDoc", "onPostExecute Called");
            if (success) {
                Intent i = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
                application.sendBroadcast(i);
            } else {
                notification.flags = notification.flags | Notification.DEFAULT_ALL;
                notification.contentView.setTextViewText(R.id.status_text, "failed");
                notificationManager.notify(id, notification);
            }

        }
    }

Le httpClient qui est passé par le fournisseur est configuré comme suit (le fournisseur est parce que j'utilise roboguice)

HttpParams params = new BasicHttpParams();

HttpRequestRetryHandler retryhandler = new DefaultHttpRequestRetryHandler(6, true);
// The params are read in the ctor of the pool constructed by
// ThreadSafeClientConnManager, and need to be set before constructing it.
ConnManagerParams.setMaxTotalConnections(params, 200);
ConnPerRoute cpr = new ConnPerRoute() {
    @Override
    public int getMaxForRoute(HttpRoute httpRoute) {
        return 50;
    }
};
ConnManagerParams.setMaxConnectionsPerRoute(params, cpr);

SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", SSLCertificateSocketFactory.getHttpSocketFactory(50000,
        new SSLSessionCache(context)), 443));

ClientConnectionManager conManager = new ThreadSafeClientConnManager(params, schemeRegistry);
DefaultHttpClient httpClient = new DefaultHttpClient(conManager, new BasicHttpParams());
httpClient.setHttpRequestRetryHandler(retryhandler);

Merci pour tout conseil

2voto

Graeme Points 9167
06-14 17:26:48.770: W/System.err(15648):    at net.doo.download.ManualDocDownloader$AsyncDocDownloader.doInBackground(ManualDocDownloader.java:126)
06-14 17:26:48.770: W/System.err(15648):    at net.doo.download.ManualDocDownloader$AsyncDocDownloader.doInBackground(ManualDocDownloader.java:86)

Cela suggère que votre code lance une exception, que votre try{}catch() propage ensuite vers le haut.

Vous devriez essayer d'attraper SSLException ainsi que IOException afin que vous puissiez récupérer et redémarrer gracieusement votre AsyncTask

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X