Un plugin pour créer et gérer des tâches de téléchargement. Prend en charge iOS et Android.
Ce plugin utilise WorkManager
sur Android et NSURLSessionDownloadTask
sur iOS pour exécuter des tâches de téléchargement en arrière-plan.
Les modifications des API de stockage externe dans Android 11 posent quelques problèmes avec la mise en œuvre actuelle. Je décide de repenser ce plugin avec une nouvelle stratégie pour gérer l'emplacement des fichiers de téléchargement. Il est toujours en cours de triage et de discussion dans ce PR. Il est très apprécié d'avoir la contribution et les commentaires du développeur Flutter pour obtenir une meilleure conception du plugin.
Dans les versions précédentes de ce package, il existait des vulnérabilités connues liées à l'injection SQL. L'injection SQL est un type de vulnérabilité de sécurité qui peut permettre à des utilisateurs malveillants de manipuler des requêtes SQL exécutées par une application, conduisant potentiellement à un accès non autorisé ou à une manipulation de la base de données.
Il est fortement recommandé de mettre à niveau vers la dernière version de ce package pour garantir que votre application n'est pas exposée aux vulnérabilités d'injection SQL. La dernière version contient les améliorations de sécurité et les correctifs nécessaires pour atténuer ces risques.
Les étapes suivantes nécessitent d'ouvrir votre projet ios
dans Xcode.
Activez le mode arrière-plan.
Ajoutez la bibliothèque sqlite
.
Configurer AppDelegate
:
Objectif-C :
/// AppDelegate.h#import#import @interface AppDelegate : FlutterAppDelegate@end
// AppDelegate.m#include "AppDelegate.h"#include "GeneratedPluginRegistrant.h"#include "FlutterDownloaderPlugin.h"@implementation AppDelegatevoid registerPlugins(NSObject* registre) { if (![registry hasPlugin:@"FlutterDownloaderPlugin" ]) { [FlutterDownloaderPlugin registerWithRegistrar :[registry registrarForPlugin :@"FlutterDownloaderPlugin"]] ; } } - (BOOL)application :(UIApplication *)application didFinishLaunchingWithOptions :(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; [FlutterDownloaderPlugin setPluginRegistrantCallback:registerPlugins] ; // Remplacer le point de personnalisation après le lancement de l'application. return [super application:application didFinishLaunchingWithOptions:launchOptions] ; }@fin
Ou Swift :
importer UIKit importer Flutter import flutter_downloader@UIApplicationMain@objc class AppDelegate : FlutterAppDelegate { override func application ( _ application : UIApplication, didFinishLaunchingWithOptions launchOptions : [UIApplication.LaunchOptionsKey : Any] ? ) -> Bool { GeneratedPluginRegistrant.register(with: self) FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins) return super.application(application, didFinishLaunchingWithOptions: launchOptions) }}fonction privée registerPlugins(registre : FlutterPluginRegistry) { if (!registry.hasPlugin("FlutterDownloaderPlugin")) { FlutterDownloaderPlugin.register(with: Registry.registrar(forPlugin: "FlutterDownloaderPlugin")!) }}
Prise en charge de la requête HTTP : si vous souhaitez télécharger un fichier avec une requête HTTP, vous devez désactiver la fonctionnalité Apple Transport Security (ATS). Il y a deux options :
Désactivez ATS pour un domaine spécifique uniquement : (ajoutez le code suivant à votre fichier Info.plist
)
NSAppTransportSecurity NSExceptionDomains www.votreserveur.com NSIncludesSubdomains NSTemporaryExceptionAllowsInsecureHTTPLoads NSTemporaryExceptionMinimumTLSVersion TLSv1.1
Désactivez complètement ATS. Ajoutez ce qui suit à votre fichier Info.plist
)
NSAppTransportSecurity NSAllowsArbitraryLoads
Configurez le nombre maximum de tâches simultanées : le plugin autorise 3 tâches de téléchargement exécutées à la fois par défaut (si vous mettez plus de 3 tâches en file d'attente, il n'y a que 3 tâches en cours d'exécution, les autres tâches sont mises en attente). Vous pouvez modifier ce numéro en ajoutant le code suivant à votre fichier Info.plist
.
FDMaximumConcurrentTasks 5
Localiser les messages de notification : le plugin enverra un message de notification pour avertir l'utilisateur si tous les fichiers sont téléchargés alors que votre application ne s'exécute pas au premier plan. Ce message est en anglais par défaut. Vous pouvez localiser ce message en ajoutant et en localisant le message suivant dans le fichier Info.plist
. (vous pouvez retrouver le détail de la localisation Info.plist
dans ce lien)
FDAllFilesDownloadedMessage Tous les fichiers ont été téléchargés
Note:
Ce plugin prend uniquement en charge la sauvegarde des fichiers dans NSDocumentDirectory
Vous n’avez rien d’autre à faire pour que le plugin fonctionne sur Android.
Il existe cependant quelques paramètres facultatifs que vous souhaiterez peut-être configurer.
Pour que l'appui sur la notification ouvre le fichier téléchargé sur Android, ajoutez le code suivant à AndroidManifest.xml
:
Remarques
Vous devez enregistrer vos fichiers téléchargés sur un stockage externe (où les autres applications ont la permission de lire vos fichiers)
Les fichiers téléchargés ne peuvent être ouverts que si votre appareil dispose d'au moins une application capable de lire ces types de fichiers (mp3, pdf, etc.)
Le plugin dépend de la bibliothèque WorkManager
et WorkManager
dépend du nombre de processeurs disponibles pour configurer le nombre maximum de tâches exécutées à un moment donné. Vous pouvez configurer un numéro fixe pour cette configuration en ajoutant le code suivant à votre AndroidManifest.xml
:
Vous pouvez localiser les textes dans les notifications de progression du téléchargement en localisant les messages suivants.
Téléchargement démarré Téléchargement en cours Téléchargement annulé Échec du téléchargement Téléchargement terminé Téléchargement suspendu
Vous pouvez en savoir plus sur la localisation sur Android ici.
Pour ouvrir et installer des fichiers .apk
, votre application a besoin de l'autorisation REQUEST_INSTALL_PACKAGES
. Ajoutez ce qui suit dans votre AndroidManifest.xml
:
Voir aussi :
Correction d'une erreur Cleartext Traffic sur Android 9 Pie
import 'package:flutter_downloader/flutter_downloader.dart';void main() { WidgetsFlutterBinding.ensureInitialized(); // Le plugin doit être initialisé avant d'utiliser wait FlutterDownloader.initialize( debug : true, // facultatif : défini sur false pour désactiver l'impression des journaux sur la console (par défaut : true) ignoreSsl : true // option : définie sur false pour désactiver l'utilisation des liens http (par défaut : false) ); exécuterApp(/*...*/) }
final taskId = attendre FlutterDownloader.enqueue ( url : 'votre lien de téléchargement', en-têtes : {}, // facultatif : en-tête envoyé avec l'URL (jeton d'authentification, etc.) saveDir : 'le chemin du répertoire dans lequel vous souhaitez enregistrer les fichiers téléchargés', showNotification : true, // affiche la progression du téléchargement dans la barre d'état (pour Android) openFileFromNotification : true, // cliquez sur la notification pour ouvrir le fichier téléchargé (pour Android) );
attendre FlutterDownloader.registerCallback(callback); // le rappel est une fonction de niveau supérieur ou statique
Important
L'interface utilisateur est rendue sur l'isolat principal, tandis que les événements de téléchargement proviennent de l'isolat en arrière-plan (en d'autres termes, le code du callback
est exécuté dans l'isolat en arrière-plan), vous devez donc gérer la communication entre deux isolats. Par exemple:
ReceiverPort _port = ReceiverPort();@overridevoid initState() { super.initState(); IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port'); _port.listen((données dynamiques) { String id = data[0]; DownloadTaskStatus status = DownloadTaskStatus(data[1]); int progress = data[2]; setState((){ }); }); FlutterDownloader.registerCallback(downloadCallback); }@overridevoid dispose() { IsolateNameServer.removePortNameMapping('downloader_send_port'); super.dispose(); }@pragma('vm:entry-point')static void downloadCallback(String id, int status, int progress) { final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port'); send.send([id, statut, progression]); }
@pragma('vm:entry-point')
doit être placé au-dessus de la fonction callback
pour éviter le tremblement de l'arborescence en mode release pour Android.
tâches finales = attendre FlutterDownloader.loadTasks();
tâches finales = attendre FlutterDownloader.loadTasksWithRawQuery(query: query);
Afin d'analyser correctement les données dans l'objet DownloadTask
, vous devez charger les données avec tous les champs de la base de données (en d'autres termes, utilisez SELECT *
). Par exemple:
SELECT * FROM tâche WHERE statut=3
Vous trouverez ci-dessous le schéma de la table task
dans laquelle le plugin flutter_downloader
stocke les informations sur les tâches de téléchargement.
CREATE TABLE `task` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `task_id` VARCHAR ( 256 ), `url` TEXT, `status` INTEGER DEFAULT 0, `progress` INTEGER DEFAULT 0, `file_name` TEXTE, `saved_dir` TEXTE , `resumable` 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()
renverra un nouveau taskId
correspondant à une nouvelle tâche en arrière-plan créée pour poursuivre le processus de téléchargement. Vous devez remplacer l'ancien taskId
(qui a un statut paused
) par le nouveau taskId
pour continuer à suivre la progression du téléchargement.
FlutterDownloader.retry (taskId : taskId);
retry()
renverra un nouveau taskId
(tout comme resume()
)
FlutterDownloader.remove(taskId: taskId, ShouldDeleteContent:false);
FlutterDownloader.open(taskId : taskId);
Sur Android, vous ne pouvez ouvrir un fichier téléchargé que s'il est placé dans le stockage externe et s'il existe au moins une application capable de lire ce type de fichier sur votre appareil.
N'hésitez pas à ouvrir un ticket si vous rencontrez des problèmes ou si vous pensez qu'il manque certaines fonctionnalités au plugin.
Les demandes de tirage sont également les bienvenues !