Tip Android #20: el servicio Download Manager

14/05/2013
android tip

El servicio del sistema Download Manager fue introducido en Gingerbread y está diseñado para realizar en segundo plano descarga de grandes archivos encargándose se la gestión de las conexiones o de la conectividad. En este tip vamos a ver un ejemplo muy básico de su uso para que el lector pueda empezar a utilizarlo en sus aplicaciones si necesita esta funcionalidad

Vamos a implementar una aplicación de ejemplo que constará de dos botones: uno para realizar una descarga de un fichero del blog y guardarla en el almacenamiento externo, y otro para ver las últimas descargas realizadas a través de este servicio. El layout es el siguiente:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center">

    <Button
        android:id="@+id/buttonDownload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/descargar" 
        android:onClick="descargar"/>

    <Button
        android:id="@+id/buttonDescargas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="@string/ver" 
        android:onClick="ver"/>

</LinearLayout>

Necesitamos los siguientes permisos en el Manifest de la app

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Todo el código que vamos a ver queda en la Activity y se muestra comentado a continuación. En el método descargar se obtiene el servicio y se solicita la descarga deseada. La respuesta del servicio al finalizarse la descarga será procesada en un BroadcastReceiver que tendremos que registrar debidamente.

package com.danielme.tipsandroid.downloadmanager;

import java.io.File;
import java.io.FileNotFoundException;

import android.app.Activity;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.view.View;
import android.widget.Toast;

import com.danieme.tipsandroid.downloadmanager.R;


/**
 * 
 * @author danielme.com
 *
 */
public class MainActivity extends Activity
{
	//id de la descarga solicitada (tener en cuenta que el servicio puede gestionar múltiples descargas simultáneas)
	private long id;
	
	private DownloadManager downloadManager;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);	
		//registramos el receiver para ser notificados del final de la descarga
		IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
	        registerReceiver(downloadReceiver, filter);
	}
	
	 @Override
	 protected void onResume() 
	 {	 
		super.onResume();	    
		IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
		registerReceiver(downloadReceiver, intentFilter);
	 }
	  
	 @Override
	 protected void onPause() 
	 {
		super.onPause();	    
	    unregisterReceiver(downloadReceiver);
	 }
	
	public void descargar(View button)
	{
		downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
		DownloadManager.Request request = new DownloadManager.Request(Uri.parse("https://danielmedotcom.files.wordpress.com/2012/02/icon-danielme.png?w=630"));
		//podemos limitar la descarga a un tipo de red (opcional) 
		//IMPORTANTE: esta opción la comento porque da problemas en el emulador 
		//request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
		//esta información  se mostrará en el área de notificaciones
		request.setTitle("Descarga");
		request.setDescription("Prueba del servicio Download Manager.");

		//vamos a guardar el fichero (opcional). ver tip 5
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
		{ 
			request.setDestinationInExternalFilesDir(this, Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "tipsAndroid",System.currentTimeMillis() + "danielme.png");
		}
		
		//iniciamos la descarga
		id = downloadManager.enqueue(request);
		
	}
	
	//muestra las últimas descargas realizadas con el servicio
	public void ver(View button)
	{
	  Intent intent = new Intent();
	  intent.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS);
	  startActivity(intent);		
	}
	
	 private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
		  
		 //gestionamos la finalización de la descarga
		  @Override
		  public void onReceive(Context context, Intent intent) 
		  {
		   DownloadManager.Query query = new DownloadManager.Query();
		   query.setFilterById(id, 0);
		   Cursor cursor = downloadManager.query(query);
		     
		   if(cursor.moveToFirst())
		   {
		    int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
		    int reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON));
		      
		    if(status == DownloadManager.STATUS_SUCCESSFUL)
		    {
		    	//podemos recuperar el fichero descargado
		   	  	ParcelFileDescriptor file = null;
				try 
				{
					file = downloadManager.openDownloadedFile(id);
					Toast.makeText(MainActivity.this,"Fichero obtenido con éxito!! ",Toast.LENGTH_LONG).show();
				} 
				catch (FileNotFoundException ex) 
				{				
					Toast.makeText(MainActivity.this,"Exception: " + ex.getMessage(),Toast.LENGTH_LONG).show();
				}		      
		     } 	   
		       
		   else if(status == DownloadManager.STATUS_FAILED)
		   {
		     Toast.makeText(MainActivity.this,"FAILED: " + reason,Toast.LENGTH_LONG).show();
		   }
		   else if(status == DownloadManager.STATUS_PAUSED)
		   {
		     Toast.makeText(MainActivity.this, "PAUSED: " + reason, Toast.LENGTH_LONG).show();
		    }
		   else if(status == DownloadManager.STATUS_PENDING)
		   {
			Toast.makeText(MainActivity.this, "PENDING: " + reason, Toast.LENGTH_LONG).show();

		    }
		   else if(status == DownloadManager.STATUS_RUNNING)
		   {
			     Toast.makeText(MainActivity.this, "RUNNING: " + reason, Toast.LENGTH_LONG).show();
		    }
		   }
		  }
		    
     };
	
}

De forma totalmente automática, las descargas en curso se muestran en la barra de notificaciones. Para informar de su finalización o cualquier incidencia, se ha optado por los Toast que podeis ver en la Activity anterior.

download manager

Pulsando el botón ver descargas, accedemos a la siguiente aplicación:

últimas descargas

El proyecto completo para Eclipse ADT se encuentra en Github. Para más información sobre cómo utilizar GitHub, consultar este artículo.

<< TIPS ANDROID

Un comentario sobre “Tip Android #20: el servicio Download Manager

  1. Hola, excelente articulo, mi pregunta seria, yo quisiera que el archivo que se descargue se instale en la siguiente ruta del movil /games/com.mojang/minecraftWorlds , como seria posible esto, si me pudieras ayudar, gracias, saludos..

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.