Un complemento para crear y administrar tareas de descarga. Soporta iOS y Android.
Este complemento utiliza WorkManager
en Android y NSURLSessionDownloadTask
en iOS para ejecutar tareas de descarga en segundo plano.
Los cambios de las API de almacenamiento externo en Android 11 provocan algunos problemas con la implementación actual. Decido rediseñar este complemento con una nueva estrategia para administrar la ubicación del archivo de descarga. Todavía está en clasificación y discusión en este PR. Se agradece mucho la contribución y los comentarios del desarrollador de Flutter para obtener un mejor diseño para el complemento.
En versiones anteriores de este paquete, se conocían vulnerabilidades relacionadas con la inyección SQL. La inyección SQL es un tipo de vulnerabilidad de seguridad que puede permitir a usuarios malintencionados manipular consultas SQL ejecutadas por una aplicación, lo que podría conducir a un acceso no autorizado o manipulación de la base de datos.
Se recomienda encarecidamente actualizar a la última versión de este paquete para garantizar que su aplicación no esté expuesta a vulnerabilidades de inyección SQL. La última versión contiene las mejoras de seguridad y parches necesarios para mitigar dichos riesgos.
Los siguientes pasos requieren abrir su proyecto ios
en Xcode.
Habilite el modo en segundo plano.
Agregue la 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" ]) { [Registro FlutterDownloaderPluginWithRegistrar:[registro registradorForPlugin:@"FlutterDownloaderPlugin"]]; } } - (BOOL)aplicación:(UIApplication *)aplicación didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [RegistroGeneradoPluginRegistrantWithRegistry:self]; [FlutterDownloaderPlugin setPluginRegistrantCallback:registerPlugins]; // Anular el punto para la personalización después del inicio de la aplicación. return [súper aplicación:aplicación didFinishLaunchingWithOptions:launchOptions]; }@fin
O rápido:
importar UIKit importar aleteo importar flutter_downloader@UIApplicationMain@objc clase AppDelegate: FlutterAppDelegate { anular la aplicación func( _ aplicación: aplicación UIA, didFinishLaunchingWithOptions opciones de lanzamiento: [UIApplication.LaunchOptionsKey: cualquiera]? ) -> Bool { GeneratedPluginRegistrant.register(con: self) FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins) return super.application(aplicación, didFinishLaunchingWithOptions: launchOptions) }}función privada RegisterPlugins(registro: FlutterPluginRegistry) { if (!registry.hasPlugin("FlutterDownloaderPlugin")) { FlutterDownloaderPlugin.register(con: registro.registrar(forPlugin: "FlutterDownloaderPlugin")!) }}
Admite solicitud HTTP: si desea descargar un archivo con solicitud HTTP, debe desactivar la función Apple Transport Security (ATS). Hay dos opciones:
Deshabilite ATS solo para un dominio específico: (agregue el siguiente código a su archivo Info.plist
)
NSAppTransportSecurity Dominios NSException www.tuservidor.com NSIncluyeSubdominios NSTemporaryExceptionAllowsInsecureHTTPLoads NSTemporaryExceptionMinimumTLSVersion TLSv1.1
Desactive completamente el ATS. Agregue lo siguiente a su archivo Info.plist
)
NSAppTransportSecurity NSAllowsArbitraryLoads
Configure el número máximo de tareas simultáneas: el complemento permite que se ejecuten 3 tareas de descarga a la vez de forma predeterminada (si pone en cola más de 3 tareas, solo hay 3 tareas en ejecución, otras tareas se ponen en estado pendiente). Puede cambiar este número agregando el siguiente código a su archivo Info.plist
.
FDMaximumConcurrentTasks 5
Localizar mensajes de notificación: el complemento enviará un mensaje de notificación para notificar al usuario en caso de que todos los archivos se descarguen mientras su aplicación no se está ejecutando en primer plano. Este mensaje está en inglés de forma predeterminada. Puede localizar este mensaje agregando y localizando el siguiente mensaje en el archivo Info.plist
. (puede encontrar el detalle de la localización de Info.plist
en este enlace)
FDAllFilesDownloadedMessage Todos los archivos han sido descargados
Nota:
Este complemento solo admite archivos guardados en NSDocumentDirectory
No tienes que hacer nada adicional para que el complemento funcione en Android.
Aunque existen algunas configuraciones opcionales que quizás quieras configurar.
Para hacer que al tocar la notificación se abra el archivo descargado en Android, agregue el siguiente código a AndroidManifest.xml
:
Notas
Tienes que guardar tus archivos descargados en un almacenamiento externo (donde las otras aplicaciones tienen permiso para leer tus archivos)
Los archivos descargados solo se pueden abrir si su dispositivo tiene al menos una aplicación que pueda leer estos tipos de archivos (mp3, pdf, etc.)
El complemento depende de la biblioteca WorkManager
y WorkManager
depende de la cantidad de procesadores disponibles para configurar la cantidad máxima de tareas que se ejecutan en un momento. Puede configurar un número fijo para esta configuración agregando el siguiente código a su AndroidManifest.xml
:
Puede localizar textos en notificaciones de progreso de descarga localizando los siguientes mensajes.
Descarga iniciada Descarga en curso Descarga cancelada Descarga fallida Descarga completa Descarga pausada
Puede obtener más información sobre la localización en Android aquí.
Para abrir e instalar archivos .apk
, su aplicación necesita el permiso REQUEST_INSTALL_PACKAGES
. Agregue lo siguiente en su AndroidManifest.xml
:
Ver también:
Solucionar el error de tráfico de texto sin cifrar en Android 9 Pie
importar 'paquete:flutter_downloader/flutter_downloader.dart';void main() { WidgetsFlutterBinding.ensureInitialized(); // El complemento debe inicializarse antes de usarlo await FlutterDownloader.initialize( depuración: verdadero, // opcional: establecido en falso para deshabilitar la impresión de registros en la consola (predeterminado: verdadero) ignoreSsl: true // opción: establezca en false para deshabilitar el trabajo con enlaces http (predeterminado: false) ); ejecutarAplicación(/*...*/) }
final taskId = esperar FlutterDownloader.enqueue ( URL: 'tu enlace de descarga', encabezados: {}, // opcional: encabezado enviado con URL (token de autenticación, etc.) saveDir: 'la ruta del directorio donde desea guardar los archivos descargados', showNotification: true, // muestra el progreso de la descarga en la barra de estado (para Android) openFileFromNotification: true, // haga clic en la notificación para abrir el archivo descargado (para Android));
espere FlutterDownloader.registerCallback (devolución de llamada); // la devolución de llamada es una función estática o de nivel superior
Importante
La interfaz de usuario se representa en el aislamiento principal, mientras que los eventos de descarga provienen del aislamiento en segundo plano (en otras palabras, el código en callback
se ejecuta en el aislamiento en segundo plano), por lo que debe manejar la comunicación entre dos aislados. Por ejemplo:
PuertoRecepción _puerto = PuertoRecepción();@overridevoid initState() { super.initState(); IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port'); _port.listen((datos dinámicos) { ID de cadena = datos[0]; estado de DownloadTaskStatus = DownloadTaskStatus(datos[1]); int progreso = datos[2]; setState((){ }); }); FlutterDownloader.registerCallback(descargarCallback); }@overridevoid dispose() { IsolateNameServer.removePortNameMapping('downloader_send_port'); super.dispose(); }@pragma('vm:entry-point')descarga estática vacíaCallback(ID de cadena, estado int, progreso int) { final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port'); enviar.enviar([id, estado, progreso]); }
@pragma('vm:entry-point')
debe colocarse encima de la función callback
para evitar que el árbol se sacuda en el modo de lanzamiento para Android.
tareas finales = esperan FlutterDownloader.loadTasks();
tareas finales = await FlutterDownloader.loadTasksWithRawQuery (consulta: consulta);
Para analizar datos en el objeto DownloadTask
con éxito, debe cargar datos con todos los campos de la base de datos (en otras palabras, use SELECT *
). Por ejemplo:
SELECCIONAR * DE la tarea DONDE estado = 3
A continuación se muestra el esquema de la tabla de task
donde el complemento flutter_downloader
almacena información sobre las tareas de descarga.
CREAR TABLA `tarea` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `task_id` VARCHAR (256), `url` TEXTO, `status` INTEGER DEFAULT 0, `progreso` INTEGER DEFAULT 0, `file_name` TEXTO, `saved_dir` TEXTO , `resumable` TINYINT DEFAULT 0, `headers` TEXTO, `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: tareaId);
FlutterDownloader.resume(taskId: taskId);
resume()
devolverá un nuevo taskId
correspondiente a una nueva tarea en segundo plano que se crea para continuar el proceso de descarga. Debe reemplazar el antiguo taskId
(que tiene un estado paused
) por el nuevo taskId
para continuar rastreando el progreso de la descarga.
FlutterDownloader.retry(taskId: taskId);
retry()
devolverá un nuevo taskId
(al igual que resume()
)
FlutterDownloader.remove(taskId: taskId, deberíaDeleteContent:false);
FlutterDownloader.open(taskId: tareaId);
En Android, solo puedes abrir un archivo descargado si está colocado en el almacenamiento externo y hay al menos una aplicación que puede leer ese tipo de archivo en tu dispositivo.
No dude en abrir un problema si encuentra algún problema o cree que al complemento le falta alguna característica.
¡Las solicitudes de extracción también son bienvenidas!