Estou tentando escrever um aplicativo simples que é atualizado. Para isso, preciso de uma função simples que possa baixar um arquivo e mostrar o progresso atual em um arquivo ProgressDialog
. Eu sei como fazer isso ProgressDialog
, mas não tenho certeza de como exibir o progresso atual e como baixar o arquivo em primeiro lugar.
java
android
download
android-asynctask
Tom Leese
fonte
fonte
Respostas:
Existem várias maneiras de baixar arquivos. A seguir, publicarei as formas mais comuns; cabe a você decidir qual método é melhor para seu aplicativo.
1. Use
AsyncTask
e mostre o progresso do download em uma caixa de diálogoEste método permitirá que você execute alguns processos em segundo plano e atualize a interface do usuário ao mesmo tempo (nesse caso, atualizaremos uma barra de progresso).
Importações:
Este é um código de exemplo:
A
AsyncTask
aparência será assim:O método acima (
doInBackground
) é executado sempre em um encadeamento em segundo plano. Você não deve executar nenhuma tarefa de interface do usuário lá. Por outro lado, oonProgressUpdate
eonPreExecute
executado no segmento interface do usuário, por isso não é possível alterar a barra de progresso:Para que isso seja executado, você precisa da permissão WAKE_LOCK.
2. Baixe do Serviço
A grande questão aqui é: como atualizo minha atividade de um serviço? . No próximo exemplo, vamos usar duas classes que você talvez não saiba:
ResultReceiver
eIntentService
.ResultReceiver
é o que nos permitirá atualizar nosso encadeamento a partir de um serviço;IntentService
é uma subclasse daService
qual gera um encadeamento paraService
executar o trabalho em segundo plano a partir daí (você deve saber que um é executado no mesmo encadeamento do seu aplicativo; quando você se estendeService
, deve gerar manualmente novos encadeamentos para executar operações de bloqueio de CPU).O serviço de download pode ficar assim:
Adicione o serviço ao seu manifesto:
E a atividade ficará assim:
Aqui está onde
ResultReceiver
vem para jogar:2.1 Usar biblioteca Groundy
Groundy é uma biblioteca que basicamente ajuda a executar trechos de código em um serviço em segundo plano e é baseada no
ResultReceiver
conceito mostrado acima. Esta biblioteca está obsoleta no momento. É assim que ocódigo inteiro ficaria:A atividade em que você está mostrando a caixa de diálogo ...
Uma
GroundyTask
implementação usada pelo Groundy para baixar o arquivo e mostrar o progresso:E basta adicionar isso ao manifesto:
Não poderia ser mais fácil, eu acho. Basta pegar o pote mais recente do Github e você está pronto para começar. Lembre-se de que o principal objetivo do Groundy é fazer chamadas para APIs REST externas em um serviço em segundo plano e postar resultados na interface do usuário com facilidade. Se você estiver fazendo algo assim no seu aplicativo, pode ser realmente útil.
2.2 Use https://github.com/koush/ion
3. Use
DownloadManager
classe (GingerBread
e apenas mais recentes)O GingerBread trouxe um novo recurso,
DownloadManager
que permite baixar arquivos facilmente e delegar o trabalho árduo de lidar com threads, fluxos, etc. no sistema.Primeiro, vamos ver um método utilitário:
O nome do método explica tudo. Quando tiver certeza de que
DownloadManager
está disponível, você pode fazer algo assim:O progresso do download será exibido na barra de notificação.
Pensamentos finais
Primeiro e segundo métodos são apenas a ponta do iceberg. Há muitas coisas que você deve ter em mente se quiser que seu aplicativo seja robusto. Aqui está uma breve lista:
INTERNET
eWRITE_EXTERNAL_STORAGE
); tambémACCESS_NETWORK_STATE
se você quiser verificar a disponibilidade da Internet.A menos que você precise de controle detalhado do processo de download, considere usar
DownloadManager
(3) porque ele já lida com a maioria dos itens listados acima.Mas considere também que suas necessidades podem mudar. Por exemplo,
DownloadManager
não há cache de resposta . Ele fará o download cego do mesmo arquivo grande várias vezes. Não há uma maneira fácil de corrigi-lo após o fato. Onde se você começar com um básicoHttpURLConnection
(1, 2), tudo o que precisa é adicionar umHttpResponseCache
. Portanto, o esforço inicial de aprender as ferramentas básicas e padrão pode ser um bom investimento.fonte
close()
os fluxos (input
eoutput
) emfinally
vez detry
, caso contrário, se alguma exceção for lançada antesclose()
, você terá fluxos não fechados por aí.sdcard/
use emEnvironment.getExternalStorageDirectory()
vez disso.Não se esqueça de adicionar permissões ao seu arquivo de manifesto se você estiver baixando coisas da Internet!
fonte
Sim, o código acima irá trabalhar .Mas se você está atualizando seu
progressbar
emonProgressUpdate
deAsynctask
e você pressionar o botão de volta ou terminar sua atividadeAsyncTask
perde a sua pista com o seu UI .E quando você voltar para a sua actividade, mesmo que o download estiver em execução no fundo você vai ver nenhuma atualização na barra de progresso. Portanto,OnResume()
tente executar um encadeamento comorunOnUIThread
em uma tarefa de timer que atualiza seuprogressbar
valor com a atualização doAsyncTask
fundo em execução.Não se esqueça de Destruir o encadeamento quando sua atividade não estiver visível.
fonte
Eu recomendo que você use o meu Projeto Netroid , baseado no Volley . Eu adicionei alguns recursos, como retorno de chamada em vários eventos, gerenciamento de download de arquivos. Isso pode ser de alguma ajuda.
fonte
SSLSocketFactory
adicionando umHostnameVerifier
não é possível e eu preciso desse verificador. Levantou um problema sobre isso.Eu modifiquei a
AsyncTask
classe para lidar com a criação deprogressDialog
no mesmo contexto. Acho que o código a seguir será mais reutilizável. (pode ser chamado a partir de qualquer atividade, basta passar o contexto, o arquivo de destino, a mensagem de diálogo)fonte
Não se esqueça de substituir "/ sdcard ..." por novo arquivo ("/ mnt / sdcard / ..."), caso contrário, você receberá uma FileNotFoundException
fonte
Environment.getExternalStorageDirectory().getAbsolutePath()
para obter um caminho para o sdcard. Também não se esqueça de verificar se o armazenamento externo é montado -Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
( Mannaz )Achei este post de blog muito útil, está usando loopJ para baixar arquivo, ele tem apenas uma função Simples, será útil para alguns novos caras do Android.
fonte
Enquanto eu começava a aprender o desenvolvimento do Android, eu aprendi que esse
ProgressDialog
é o caminho a percorrer. Existe umsetProgress
métodoProgressDialog
que pode ser chamado para atualizar o nível de progresso à medida que o arquivo é baixado.O melhor que eu já vi em muitos aplicativos é que eles personalizam os atributos dessa caixa de diálogo de progresso para dar uma aparência melhor à caixa de diálogo de progresso do que a versão padrão. É bom manter o usuário envolvido com algumas animações como sapo, elefante ou gatos / cachorros fofos. Qualquer animação na caixa de diálogo de progresso atrai os usuários e eles não sentem vontade de ficar esperando por muito tempo.
fonte
Meu conselho pessoal é usar a caixa de diálogo Progresso e criar antes da execução, ou iniciar em
OnPreExecute()
, publicar o progresso com freqüência, se você usar a barra de estilo horizontal de progresso da caixa de diálogo de progresso. A parte restante é otimizar o algoritmo dedoInBackground
.fonte
Use a biblioteca de consultas do Android, muito legal mesmo. Você pode alterá-lo para usar
ProgressDialog
como você vê em outros exemplos, este mostrará a exibição de progresso do seu layout e ocultará após a conclusão.fonte
Estou adicionando outra resposta para outra solução que estou usando agora porque o Android Query é muito grande e sem manutenção para manter a saúde. Então, mudei para este https://github.com/amitshekhariitbhu/Fast-Android-Networking .
fonte
Permissões
Usando HttpURLConnection
fonte
Você pode observar o progresso do gerenciador de downloads usando LiveData e coroutines, veja a lista abaixo
https://gist.github.com/FhdAlotaibi/678eb1f4fa94475daf74ac491874fc0e
fonte
Importante
O AsyncTask está obsoleto no Android 11.
Para mais informações, verifique as seguintes postagens
Provavelmente deve passar para o quadro de concorência, conforme sugerido pelo google
fonte
Podemos usar a rotina e o gerenciador de trabalho para baixar arquivos no kotlin.
Adicione uma dependência no build.gradle
Classe WorkManager
Iniciar o download através do gerente de trabalho na classe de atividade
fonte