Um plugin para criar e gerenciar tarefas de download. Suporta iOS e Android.
Este plugin usa WorkManager
no Android e NSURLSessionDownloadTask
no iOS para executar tarefas de download em segundo plano.
As mudanças nas APIs de armazenamento externo no Android 11 causam alguns problemas na implementação atual. Decido redesenhar este plugin com uma nova estratégia para gerenciar a localização do arquivo de download. Ainda está em triagem e discussão neste PR. Agradecemos muito a contribuição e feedback do desenvolvedor do Flutter para obter um design melhor para o plugin.
Nas versões anteriores deste pacote, havia vulnerabilidades conhecidas relacionadas à injeção de SQL. A injeção de SQL é um tipo de vulnerabilidade de segurança que pode permitir que usuários mal-intencionados manipulem consultas SQL executadas por um aplicativo, levando potencialmente ao acesso não autorizado ou à manipulação do banco de dados.
É altamente recomendável atualizar para a versão mais recente deste pacote para garantir que seu aplicativo não fique exposto a vulnerabilidades de injeção de SQL. A versão mais recente contém as melhorias e patches de segurança necessários para mitigar esses riscos.
As etapas a seguir exigem a abertura do seu projeto ios
no Xcode.
Ative o modo de fundo.
Adicione a biblioteca sqlite
.
Configurar AppDelegate
:
Objetivo-C:
/// AppDelegate.h#import#import @interface AppDelegate : FlutterAppDelegate@end
// AppDelegate.m#include "AppDelegate.h"#include "GeneratedPluginRegistrant.h"#include "FlutterDownloaderPlugin.h"@implementation AppDelegatevoid registerPlugins(NSObject* registro) { if (![registry hasPlugin:@"FlutterDownloaderPlugin" ]) { [FlutterDownloaderPlugin registreWithRegistrar:[registry registrarForPlugin:@"FlutterDownloaderPlugin"]]; } } - (BOOL)aplicativo:(UIApplication *)aplicativo didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant RegisterWithRegistry:self]; [FlutterDownloaderPlugin setPluginRegistrantCallback:registerPlugins]; // Substituir ponto para personalização após inicialização do aplicativo. return [super aplicativo: aplicativo didFinishLaunchingWithOptions:launchOptions]; }@fim
Ou rápido:
importar UIKit importar vibração importar flutter_downloader@UIApplicationMain@objc class AppDelegate: FlutterAppDelegate {substituir func application( _ aplicação: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Qualquer]? ) -> Bool { GeneratedPluginRegistrant.register (com: self) FlutterDownloaderPlugin.setPluginRegistrantCallback (registerPlugins) return super.application (application, didFinishLaunchingWithOptions: launchOptions) }}private func RegisterPlugins (registro: FlutterPluginRegistry) { if (!registry.hasPlugin("FlutterDownloaderPlugin")) { FlutterDownloaderPlugin.register(com: Registry.registrar(forPlugin: "FlutterDownloaderPlugin")!) }}
Suporte a solicitação HTTP: se você deseja baixar o arquivo com solicitação HTTP, você precisa desabilitar o recurso Apple Transport Security (ATS). Existem duas opções:
Desative o ATS apenas para um domínio específico: (adicione o seguinte código ao seu arquivo Info.plist
)
NSAppTransportSecurity NSExceptionDomains www.seuservidor.com NSIncludesSubdomínios NSTemporaryExceptionAllowsInsecureHTTPLoads NSTemporaryExceptionMinimumTLSVersion TLSv1.1
Desative completamente o ATS. Adicione o seguinte ao seu arquivo Info.plist
)
NSAppTransportSecurity NSAllowsArbitraryLoads
Configure o número máximo de tarefas simultâneas: o plugin permite que 3 tarefas de download sejam executadas ao mesmo tempo por padrão (se você enfileirar mais de 3 tarefas, há apenas 3 tarefas em execução, outras tarefas são colocadas em estado pendente). Você pode alterar esse número adicionando o seguinte código ao arquivo Info.plist
.
FDMaximumConcurrentTasks 5
Localizar mensagens de notificação: o plugin enviará uma mensagem de notificação para notificar o usuário caso todos os arquivos sejam baixados enquanto seu aplicativo não estiver sendo executado em primeiro plano. Esta mensagem é em inglês por padrão. Você pode localizar esta mensagem adicionando e localizando a seguinte mensagem no arquivo Info.plist
. (você pode encontrar os detalhes da localização Info.plist
neste link)
FDAllFilesDownloadedMessage Todos os arquivos foram baixados
Observação:
Este plugin só suporta salvar arquivos em NSDocumentDirectory
Você não precisa fazer nada extra para que o plugin funcione no Android.
Existem algumas configurações opcionais que você pode querer definir.
Para fazer com que o toque na notificação abra o arquivo baixado no Android, adicione o seguinte código ao AndroidManifest.xml
:
Notas
Você deve salvar os arquivos baixados em armazenamento externo (onde os outros aplicativos têm permissão para ler seus arquivos)
Os arquivos baixados só poderão ser abertos se o seu dispositivo tiver pelo menos um aplicativo que possa ler esses tipos de arquivos (mp3, pdf, etc.)
O plugin depende da biblioteca WorkManager
e WorkManager
depende da quantidade de processadores disponíveis para configurar o número máximo de tarefas em execução por momento. Você pode definir um número fixo para esta configuração adicionando o seguinte código ao seu AndroidManifest.xml
:
Você pode localizar textos em notificações de progresso de download localizando as mensagens a seguir.
Download iniciado Download em andamento Download cancelado Falha no download Download concluído Download pausado
Você pode aprender mais sobre localização no Android aqui.
Para abrir e instalar arquivos .apk
, seu aplicativo precisa da permissão REQUEST_INSTALL_PACKAGES
. Adicione o seguinte em seu AndroidManifest.xml
:
Veja também:
Corrigir erro de tráfego de texto claro no Android 9 Pie
importar 'pacote:flutter_downloader/flutter_downloader.dart';void main() { WidgetsFlutterBinding.ensureInitialized(); // O plugin deve ser inicializado antes de usar await FlutterDownloader.initialize( debug: true, // opcional: definido como false para desativar a impressão de logs no console (padrão: true) ignoreSsl: true // opção: defina como false para desabilitar o trabalho com links http (padrão: false) ); runApp(/*...*/) }
tarefa final = aguarda FlutterDownloader.enqueue ( url: 'seu link de download', headers: {}, // opcional: cabeçalho enviado com url (token de autenticação, etc.) saveDir: 'o caminho do diretório onde você deseja salvar os arquivos baixados', showNotification: true, // mostra o progresso do download na barra de status (para Android) openFileFromNotification: true, // clique na notificação para abrir o arquivo baixado (para Android));
aguarde FlutterDownloader.registerCallback(retorno de chamada); // retorno de chamada é uma função estática ou de nível superior
Importante
A UI é renderizada no isolado principal, enquanto os eventos de download vêm do isolado em segundo plano (em outras palavras, o código no callback
é executado no isolado em segundo plano), portanto, você precisa lidar com a comunicação entre dois isolados. Por exemplo:
ReceivePort _port = ReceivePort();@overridevoid initState() { super.initState(); IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port'); _port.listen((dados dinâmicos) { String id = dados[0]; DownloadTaskStatus status = DownloadTaskStatus(dados[1]); int progresso = dados[2]; setState((){ }); }); FlutterDownloader.registerCallback(downloadCallback); }@overridevoid descarte() { IsolateNameServer.removePortNameMapping('downloader_send_port'); super.dispose(); }@pragma('vm:ponto de entrada')static void downloadCallback(String id, int status, int progress) { final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port'); send.send([id, status, progresso]); }
@pragma('vm:entry-point')
deve ser colocado acima da função callback
para evitar o tremor da árvore no modo de liberação do Android.
tarefas finais = aguardar FlutterDownloader.loadTasks();
tarefas finais = aguardar FlutterDownloader.loadTasksWithRawQuery(query: query);
Para analisar os dados no objeto DownloadTask
com sucesso, você deve carregar os dados com todos os campos do banco de dados (em outras palavras, usar SELECT *
). Por exemplo:
SELECIONE * DA tarefa ONDE status = 3
Abaixo está o esquema da tabela task
onde o plugin flutter_downloader
armazena informações sobre tarefas de download
CREATE TABLE `task` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `task_id` VARCHAR ( 256 ), `url` TEXT, `status` INTEGER DEFAULT 0, `progress` INTEGER DEFAULT 0, `file_name` TEXT, `saved_dir` TEXT , `resumível` TINYINT DEFAULT 0, `headers` TEXT, `show_notification` TINYINT DEFAULT 0, `open_file_from_notification` TINYINT DEFAULT 0, `time_created` INTEGER DEFAULT 0);
FlutterDownloader.cancel(taskId: taskId);
FlutterDownloader.cancelAll();
FlutterDownloader.pause(taskId: taskId);
FlutterDownloader.resume(taskId: taskId);
resume()
retornará um novo taskId
correspondente a uma nova tarefa em segundo plano criada para continuar o processo de download. Você deve substituir o taskId
antigo (que tem status paused
) pelo novo taskId
para continuar acompanhando o progresso do download.
FlutterDownloader.retry(taskId: taskId);
retry()
retornará um novo taskId
(assim como resume()
)
FlutterDownloader.remove(taskId: taskId, shouldDeleteContent:false);
FlutterDownloader.open(taskId: taskId);
No Android, você só pode abrir um arquivo baixado se ele estiver colocado no armazenamento externo e se houver pelo menos um aplicativo que possa ler esse tipo de arquivo no seu dispositivo.
Sinta-se à vontade para abrir um problema se encontrar algum problema ou achar que falta algum recurso no plugin.
Solicitações pull também são muito bem-vindas!