No se capturan varias subclases de IOException cuando se intenta en el bloque catch

Estoy usando el siguiente método para descargar imágenes de un servidor para servir en una aplicación de Android.

public static void downloadToFile(File file, URL url, int connectTimeout, 
        int readTimeout) throws IOException {
    InputStream in = null;
    OutputStream out = null;
    try {
        URLConnection ucon = url.openConnection();
        ucon.setConnectTimeout(connectTimeout);
        ucon.setReadTimeout(readTimeout);

        in = ucon.getInputStream();
        out = new FileOutputStream(file);
        byte[] buffer = new byte[BUFFER_SIZE];
        int count = 0;
        while ((count = in.read(buffer)) != -1) {
            out.write(buffer, 0, count);
        }
        out.flush();
    } finally {
        if (in != null) {
            in.close();
        }
        if (out != null) {
            out.close();
        }
    }
}

Cuando un archivo se ha eliminado del servidor pero intento descargarlo de todos modos, recibo una FileNotFoundException, que es perfectamente válida. En mi aplicación, la llamada a este método está envuelta en un intento de captura que maneja tanto IOException como Exception para que pueda continuar.

El problema es que en la Consola de desarrollador de Android he recibido algunos informes de fallos y FileNotFoundException parece estar ignorando los bloqueos de captura y forzando el cierre de la aplicación.

java.io.FileNotFoundException: http://foo.org/1234.jpg
at   org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1162)
at com.package.IOUtil.downloadToFile(Unknown Source)

La fuente desconocida se debe a Proguard, pero puedo forzar la excepción al realizar la prueba colocando URL de archivo no existentes que arroja la excepción. Cuando pruebo en mi teléfono (SGS2 2.3.3) y tableta (TF101 3.2), el bloque try catch detecta la excepción. El seguimiento de la pila a continuación apunta a la URL # getInputStream () como lo que arroja la excepción, pero eso no explica por qué no se detecta para algunos (solo unos pocos).

java.io.FileNotFoundException: http://foo.org/1234.jpg
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:521)
at com.package.IOUtil.downloadToFile(IOUtil.java:142)

También he tenido el mismo problema con una SocketException del mismo método / llamada que no ha sido capturada.

java.net.SocketTimeoutException: Connection timed out
at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
at dalvik.system.BlockGuard$WrappedNetworkSystem.connect(BlockGuard.java:357)
at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:204)
at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:437)
at java.net.Socket.connect(Socket.java:1002)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:75)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1018)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:512)
at com.package.IOUtil.downloadToFile(Unknown Source)

La descarga se realiza en un hilo de fondo si eso importa.

¿Me estoy perdiendo de algo? ¿Podría ser específico del teléfono o Proguard (a pesar de que casi todo el mundo lo ha capturado)?

Editar: Código que atrapa

private void download(List<URL> urls, int attempts) {
    List<URL> failedDownloads = new ArrayList<URL>();
    for (URL url : urls) {
        if (isInterrupted()) {
            return;
        }

        String imageName = Util.getImageName(url);
        File cacheFile = cache.getCacheFile(imageName);
        try {
            // Bad downloads often don't throw an IOException but
            // leave the file with a length of 0.
            if (cacheFile.length() == 0) {
                Util.safeDelete(cacheFile);
            }

            if (!cacheFile.exists()) {
                IOUtil.downloadToFile(cacheFile, url);

                if (cacheFile.length() == 0) {
                    //See above
                    Util.safeDelete(cacheFile);
                    failedDownloads.add(url);
                } else {
                    if (putToCache) {
                        cache.get(imageName);
                    }
                    handler.sendEmptyMessage(0);
                }
            } else {
                // Exists already, move it to cache
                if (putToCache) {
                    cache.get(imageName);
                }
            }
        } catch (IOException ioe) {
            Util.safeDelete(cacheFile);
            failedDownloads.add(url);
        } catch (Exception e) {
            // Continue on to next download - don't bother trying this
            // URL again.
        }
    }

    if (!failedDownloads.isEmpty() && attempts < maxAttempts) {
        attempts++;
        download(failedDownloads, attempts);
    }
}

Util.safeDelete es solo una eliminación envuelta en un intento de captura, por lo que no debería estar relacionado.

Respuesta 1

La descarga se realiza en un hilo de fondo si eso importa.

Si, esto importa. La excepción se lanza en el hilo de fondo y desaparece efectivamente en el aire.

Creo que la solución se puede encontrar aquí: ¿Cómo lanzar una excepción marcada desde un hilo de Java? La respuesta que implica poner su hilo de fondo en un invocable podría ser el mejor enfoque

salud

Respuesta: 2

Es extraño que la excepción catch no capture FileNotFoundException. Parece que ya has detectado una excepción en el método de descarga.

Puede intentar detectar la excepción en downloadToFile y ver qué sucede. Ver si es un error en otro lugar ...

Respuesta: 3

Tengo un extraño problema. Estoy usando los servicios de Apache para configurar mis servicios de Windows. Según Procrun, mis archivos por lotes deberían haberse configurado para iniciar y detener servicios. mi problema es cuando comienzo mi ...

Acabo de agregar tres nuevas clases a mi aplicación; son muy similares a los existentes. La funcionalidad funciona en el entorno de desarrollo, pero no en vivo: falta al menos una clase en la implementación. Eso ...

Ejecutamos Apache delante de Tomcat y utilizamos mod_jk. Nuestro inicio de sesión único en el módulo Apache establece información sobre el usuario que podemos recuperar en Java con una llamada getAttribute (). Cadena mobileNumber = ...

Estoy tratando de usar el método renameNode () de la clase org.w3c.dom.Document para cambiar el nombre del nodo raíz de un documento XML. Mi código es similar a esto: xml.renameNode (Element, "http: // newnamespaceURI", ...