Descargar archivo en Android con indicador de progreso: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Descarga de archivos en Android: de la idea al código funcional

\n\n

Todo desarrollador de Android, tarde o temprano, se enfrenta a la tarea de descargar un archivo desde la red. Puede ser una actualización de la aplicación, la descarga de una imagen, un documento PDF o una pista de música. Pero simplemente descargar el archivo es solo la mitad del trabajo. El usuario debe ver que el proceso está en marcha: cuánto se ha descargado, cuánto falta y que la aplicación no se ha congelado.

\n\n

En este artículo, analizaremos una pregunta clásica de Stack Overflow que ha acumulado miles de visitas: cómo descargar un archivo en Android y mostrar el progreso en un cuadro de diálogo. Escribiremos el código en Java, utilizando AsyncTask y ProgressDialog (aunque en proyectos modernos a menudo se reemplazan con corrutinas o RxJava, comprender los clásicos es la base que sigue siendo fundamental).

\n\n

¿Listos? ¡Vamos allá!

\n\n

¿Por qué es tan difícil? Tres obstáculos de la descarga en Android

\n\n

A primera vista, la tarea es simple: abrir una conexión, leer el flujo de bytes y escribir en un archivo. Pero en la práctica, los desarrolladores tropiezan con tres cosas:

\n\n
    \n
  • El hilo de la UI se bloquea — si inicias la descarga en el hilo principal, la aplicación se «congelará» y Android mostrará el diálogo «La aplicación no responde».
  • \n
  • El progreso no se actualiza — incluso si cuentas los bytes, no puedes simplemente cambiar la UI desde un hilo en segundo plano.
  • \n
  • La configuración cambia — el usuario gira la pantalla y tu Activity se recrea. El diálogo desaparece y la descarga continúa sin destino.
  • \n
\n\n

Resolveremos los tres problemas. Empezaremos con la arquitectura y luego escribiremos el código.

\n\n

Elegimos las herramientas: AsyncTask y ProgressDialog

\n\n

Con fines educativos, utilizaremos el enfoque clásico:

\n
    \n
  • AsyncTask — para realizar trabajo en segundo plano y publicar el progreso.
  • \n
  • ProgressDialog — para mostrar los porcentajes.
  • \n
  • HttpURLConnection — para la solicitud HTTP (sigue vivo, aunque está obsoleto).
  • \n
\n\n

Importante: En proyectos reales, hoy en día se usa más a menudo DownloadManager, WorkManager o bibliotecas como Retrofit + OkHttp. Pero entender cómo funciona la descarga «a mano» es un must-have para cualquier desarrollador.

\n\n

Código completo: descarga de archivos con ProgressDialog

\n\n

A continuación se presenta una clase lista para usar para la descarga. El código está comentado en español para que entiendas de inmediato lo que sucede.

\n\n
import android.app.ProgressDialog;\nimport android.content.Context;\nimport android.os.AsyncTask;\nimport android.os.Environment;\nimport android.widget.Toast;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.InputStream;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\n\npublic class DownloadFileTask extends AsyncTask<String, Integer, String> {\n\n    private Context context;\n    private ProgressDialog progressDialog;\n\n    public DownloadFileTask(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    protected void onPreExecute() {\n        super.onPreExecute();\n        // Creamos y mostramos el diálogo de progreso\n        progressDialog = new ProgressDialog(context);\n        progressDialog.setTitle("Descarga de archivo");\n        progressDialog.setMessage("Descargando...");\n        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);\n        progressDialog.setCancelable(false); // No permitimos cerrarlo accidentalmente\n        progressDialog.show();\n    }\n\n    @Override\n    protected String doInBackground(String... params) {\n        String fileUrl = params[0];\n        String fileName = "downloaded_file.pdf"; // Se puede pasar como segundo parámetro\n        InputStream inputStream = null;\n        FileOutputStream outputStream = null;\n\n        try {\n            // 1. Establecemos la conexión\n            URL url = new URL(fileUrl);\n            HttpURLConnection connec                

Blogs

Book Recommendations