Cómo descargar y descomprimir un zip en Android

El primer paso es determinar si el dispositivo tiene espacio suficiente para almacenar el zip. En este caso, el código revisa el espacio del Internal Storage:

*Dado que el proceso de descarga y descompresión puede ser tardado y requerir muchos recursos del dispositivo, es recomendado hacerlo dentro de un AsyncTask para no interrumpir el uso de la app por parte del usuario

urlConnectionZipFile = finalUrl.openConnection();
urlConnectionZipFile.connect();
int contentLength = urlConnectionZipFile.getContentLength();    //Obtener el tamaño del archivo en bytes
Log.d("DEBUG", "urlConnection.getContentLength():"
        + contentLength);
/*Obtener el directorio de datos del dispositivo. Es importante usar el método <code>Environment.getDataDirectory()</code> para obtener el directorio ya que puede variar entre dispositivos, por lo que ponerlo de forma manual (por ejemplo <code>File path = "/data"</code>) arrojará una excepción en dispositivos que tengan un nombre de directorio distinto*/
File path = Environment.getDataDirectory();
 
//Obtener el espacio libre del dispositivo*/
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
 
//La memoria total del dispositivo está distribuida en N bloques*/
long availableBlocks = stat.getAvailableBlocks();
 
/*Verificar que el dispositivo tenga más espacio libre de lo que pesa el archivo*/
if (contentLength > (availableBlocks * blockSize)) {
    String espacioRequerido = Formatter.formatFileSize(mActivity, contentLength);
    String espacioDisponible = Formatter.formatFileSize(mActivity, (availableBlocks * blockSize));
    return "Ha ocurrido un error al actualizar: No hay suficiente espacio en disco para las fotos. Requerido: " + espacioRequerido + ". Disponible: " + espacioDisponible;
}

El siguiente paso es descargar el zip y guardarlo en el Internal Storage:

/*Cada aplicación tiene un directorio privado para asegurar que otras aplicaciones no puedan tener acceso a sus archivos (la aplicación puede permitir el acceso por medio del parámetro MODE_PUBLIC), accedemos a este directorio usando el método <code>Activity.getFilesDir()</code>. En este caso, guardaremos el archivo descargado en el subdirectorio data/product
File rootfolder = new File(mActivity.getFilesDir(), "data/product/");
 
InputStream input = new BufferedInputStream(finalUrl.openStream());
OutputStream output = new FileOutputStream(rootfolder + "/myawesomefile.zip");
byte data[] = new byte[4096]; //4096
int count;
while ((count = input.read(data)) != -1) {
    output.write(data, 0, count);
}
output.flush();
output.close();
input.close();

Una vez descargado el archivo, lo descomprimimos. En este ejemplo, descomprimiremos un zip que contiene una carpeta y dentro de ella contiene imagenes:

*Hay que considerar que si descomprimimos el archivo completo (como en este ejemplo), necesitaremos verificar que haya espacio espacio suficiente para hacerlo, ya que el zip seguirá existiendo y por lo tanto ocupando ese espacio que antes teníamos libre

*La clase ZipInputStream no interpreta bien archivos comprimidos en otros formatos y el resultado es que el método getNextEntry() siempre regresará un nulo. Asegurate de que el archivo a descomprimir esté en formato zip (ojo: si fue comprimido con otro formato y su extensión fue cambiada a .zip, no funcionará. Es obligatorio que haya sido comprimido como zip desde un inicio)

//Creamos un InputStream desde el archivo que acabamos de guardar en disco
InputStream downloadedZipStream = new FileInputStream(rootfolder + "/myawesomefile.zip");
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(downloadedZipStream)); 
 
//Empezamos a recorrer cada archivo dentro del zip
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
    if (ze.isDirectory()) {
        //do nothing
    } else {
        Bitmap bmp = BitmapFactory.decodeStream(zin);
        File imagePath = new File(rootfolder + "/",ze.getName().substring(21));
        FileOutputStream fos = new FileOutputStream(imagePath);
        bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
        zin.closeEntry();
        fos.close();
    }
}
zin.close();

 

El manejo de las siguientes excepciones te ayudará a detectar errores específicos en el proceso de descarga y descompresión:

catch (ProtocolException pe) {
    //posiblemente ocurrió un error en el que se interrumpió la descarga
} catch(IOException ioe) {
    /*posiblemente se deba a que alguna de las rutas especificadas no existía en el sistema de archivos del dispositivo. Recuerda usar el método File.mkdir() en caso de que estés usando sub carpetas*/
} catch (Exception e) {
    //Pon un breakpoint aquí para ver el mensaje de la excepción y poder identificar escenarios nuevos en donde el proceso arroje excepciones
}

Si ya no requerimos el archivo después de descomprimirlo, eliminarlo:

file = new File(rootfolder + "/myawesomefile.zip");
file.delete(); 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s