Download de arquivo no Android: da ideia ao código funcional
\n\nTodo desenvolvedor Android, mais cedo ou mais tarde, enfrenta a tarefa de baixar um arquivo da rede. Pode ser uma atualização de aplicativo, download de imagem, documento PDF ou faixa de música. Mas apenas baixar o arquivo é metade do trabalho. O usuário precisa ver que o processo está em andamento: quanto foi baixado, quanto falta e que o aplicativo não travou.
\n\nNeste artigo, vamos analisar uma pergunta clássica do Stack Overflow, que acumulou milhares de visualizações: como baixar um arquivo no Android e mostrar o progresso em uma caixa de diálogo. Escreveremos o código em Java, usando AsyncTask e ProgressDialog (embora em projetos modernos eles sejam frequentemente substituídos por corrotinas ou RxJava, entender o clássico é a base que não desapareceu).
Prontos? Vamos lá!
\n\nPor que é tão difícil? Três armadilhas do download no Android
\n\nÀ primeira vista, a tarefa é simples: abrir uma conexão, ler o fluxo de bytes, gravar em um arquivo. Mas na prática, os desenvolvedores tropeçam em três coisas:
\n\n- \n
- A thread da UI é bloqueada — se você iniciar o download na thread principal, o aplicativo "congela" e o Android mostra o diálogo "O aplicativo não está respondendo". \n
- O progresso não é atualizado — mesmo que você conte os bytes, não pode simplesmente alterar a UI a partir de uma thread em segundo plano. \n
- A configuração muda — o usuário girou a tela e sua
Activityfoi recriada. O diálogo desapareceu e o download está indo para lugar nenhum. \n
Vamos resolver todos os três problemas. Começaremos pela arquitetura e depois escreveremos o código.
\n\nEscolhendo as ferramentas: AsyncTask e ProgressDialog
\n\nPara fins educacionais, usaremos a abordagem clássica:
\n- \n
AsyncTask— para executar o trabalho em segundo plano e publicar o progresso. \n ProgressDialog— para exibir as porcentagens. \n HttpURLConnection— para a requisição HTTP (ainda está vivo, embora obsoleto). \n
Importante: Em projetos reais hoje, é mais comum usar DownloadManager, WorkManager ou bibliotecas como Retrofit + OkHttp. Mas entender como o download funciona "manualmente" é um must-have para qualquer desenvolvedor.
Código completo: download de arquivo com ProgressDialog
\n\nAbaixo está uma classe pronta para download. O código está comentado em português para que você entenda imediatamente o que está acontecendo.
\n\nimport 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 // Criamos e mostramos o diálogo de progresso\n progressDialog = new ProgressDialog(context);\n progressDialog.setTitle("Download de arquivo");\n progressDialog.setMessage("Baixando...");\n progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);\n progressDialog.setCancelable(false); // Não permitimos fechar acidentalmente\n progressDialog.show();\n }\n\n @Override\n protected String doInBackground(String... params) {\n String fileUrl = params[0];\n String fileName = "downloaded_file.pdf"; // Pode ser passado como segundo parâmetro\n InputStream inputStream = null;\n FileOutputStream outputStream = null;\n\n try {\n // 1. Estabelecemos a conexão\n URL url = new URL(fileUrl);\n HttpURLConnection connec