• Stars
    star
    890
  • Rank 49,469 (Top 2 %)
  • Language
    Kotlin
  • License
    BSD 3-Clause "New...
  • Created almost 6 years ago
  • Updated 11 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Flutter Downloader - A plugin for creating and managing download tasks.

flutter_community

Flutter Downloader

flutter_downloader on pub.dev

A plugin for creating and managing download tasks. Supports iOS and Android.

This plugin is using WorkManager on Android and NSURLSessionDownloadTask on iOS to run download tasks in background.

Development note:

The changes of external storage APIs in Android 11 cause some problems with the current implementation. I decide to re-design this plugin with new strategy to manage download file location. It is still in triage and discussion in this PR. It is very appreciated to have contribution and feedback from Flutter developer to get better design for the plugin.

iOS integration

Required configuration:

The following steps require to open your ios project in Xcode.

  1. Enable background mode.

  1. Add sqlite library.

  1. Configure AppDelegate:

Objective-C:

/// AppDelegate.h
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate

@end
// AppDelegate.m
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#include "FlutterDownloaderPlugin.h"

@implementation AppDelegate

void registerPlugins(NSObject<FlutterPluginRegistry>* registry) {
  if (![registry hasPlugin:@"FlutterDownloaderPlugin"]) {
     [FlutterDownloaderPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterDownloaderPlugin"]];
  }
}

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  [FlutterDownloaderPlugin setPluginRegistrantCallback:registerPlugins];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Or Swift:

import UIKit
import 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)
  }
}

private func registerPlugins(registry: FlutterPluginRegistry) {
    if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
       FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
    }
}

Optional configuration:

  • Support HTTP request: if you want to download file with HTTP request, you need to disable Apple Transport Security (ATS) feature. There're two options:
  1. Disable ATS for a specific domain only: (add the following code to your Info.plist file)
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>www.yourserver.com</key>
    <dict>
      <!-- add this key to enable subdomains such as sub.yourserver.com -->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!-- add this key to allow standard HTTP requests, thus negating the ATS -->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!-- add this key to specify the minimum TLS version to accept -->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>
  1. Completely disable ATS. Add the following to your Info.plist file)
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key><true/>
</dict>
  • Configure maximum number of concurrent tasks: the plugin allows 3 download tasks running at a moment by default (if you enqueue more than 3 tasks, there're only 3 tasks running, other tasks are put in pending state). You can change this number by adding the following code to your Info.plist file.
<!-- changes this number to configure the maximum number of concurrent tasks -->
<key>FDMaximumConcurrentTasks</key>
<integer>5</integer>
  • Localize notification messages: the plugin will send a notification message to notify user in case all files are downloaded while your application is not running in foreground. This message is English by default. You can localize this message by adding and localizing following message in Info.plist file. (you can find the detail of Info.plist localization in this link)
<key>FDAllFilesDownloadedMessage</key>
<string>All files have been downloaded</string>

Note:

  • This plugin only supports save files in NSDocumentDirectory

Android integration

You don't have to do anything extra to make the plugin work on Android.

There are although a few optional settings you might want to configure.

Open downloaded file from notification

To make tapping on notification open the downloaded file on Android, add the following code to AndroidManifest.xml:

<provider
    android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
    android:authorities="${applicationId}.flutter_downloader.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

Notes

  • You have to save your downloaded files in external storage (where the other applications have permission to read your files)
  • The downloaded files are only able to be opened if your device has at least one application that can read these file types (mp3, pdf, etc.)

Configure maximum number of concurrent download tasks

The plugin depends on WorkManager library and WorkManager depends on the number of available processor to configure the maximum number of tasks running at a moment. You can setup a fixed number for this configuration by adding the following code to your AndroidManifest.xml:

<!-- Begin FlutterDownloader customization -->
<!-- disable default Initializer -->
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>

<!-- declare customized Initializer -->
<provider
    android:name="vn.hunghd.flutterdownloader.FlutterDownloaderInitializer"
    android:authorities="${applicationId}.flutter-downloader-init"
    android:exported="false">
    <!-- changes this number to configure the maximum number of concurrent tasks -->
    <meta-data
        android:name="vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS"
        android:value="5" />
</provider>
<!-- End FlutterDownloader customization -->

Localize strings in notifications

You can localize texts in download progress notifications by localizing following messages.

<string name="flutter_downloader_notification_started">Download started</string>
<string name="flutter_downloader_notification_in_progress">Download in progress</string>
<string name="flutter_downloader_notification_canceled">Download canceled</string>
<string name="flutter_downloader_notification_failed">Download failed</string>
<string name="flutter_downloader_notification_complete">Download complete</string>
<string name="flutter_downloader_notification_paused">Download paused</string>

You can learn more about localization on Android here.

Install .apk files

To open and install .apk files, your application needs REQUEST_INSTALL_PACKAGES permission. Add the following in your AndroidManifest.xml:

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

See also:

Usage

Import and initialize

import 'package:flutter_downloader/flutter_downloader.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // Plugin must be initialized before using
  await FlutterDownloader.initialize(
    debug: true, // optional: set to false to disable printing logs to console (default: true)
    ignoreSsl: true // option: set to false to disable working with http links (default: false)
  );

  runApp(/*...*/)
}

Create new download task

final taskId = await FlutterDownloader.enqueue(
  url: 'your download link',
  headers: {}, // optional: header send with url (auth token etc)
  savedDir: 'the path of directory where you want to save downloaded files',
  showNotification: true, // show download progress in status bar (for Android)
  openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);

Update download progress

await FlutterDownloader.registerCallback(callback); // callback is a top-level or static function

Important

UI is rendered on the main isolate, while download events come from the background isolate (in other words, code in callback is run in the background isolate), so you have to handle the communication between two isolates. For example:

ReceivePort _port = ReceivePort();

@override
void initState() {
  super.initState();

  IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
  _port.listen((dynamic data) {
    String id = data[0];
    DownloadTaskStatus status = DownloadTaskStatus(data[1]);
    int progress = data[2];
    setState((){ });
  });

  FlutterDownloader.registerCallback(downloadCallback);
}

@override
void 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, status, progress]);
}

@pragma('vm:entry-point') must be placed above the callback function to avoid tree shaking in release mode for Android.

Load all download tasks

final tasks = await FlutterDownloader.loadTasks();

Load download tasks using a raw SQL query

final tasks = await FlutterDownloader.loadTasksWithRawQuery(query: query);

In order to parse data into DownloadTask object successfully, you should load data with all fields from the database (in the other words, use SELECT * ). For example:

SELECT * FROM task WHERE status=3

Below is the schema of the task table where flutter_downloader plugin stores information about download tasks

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,
  `resumable` TINYINT DEFAULT 0,
  `headers` TEXT,
  `show_notification` TINYINT DEFAULT 0,
  `open_file_from_notification` TINYINT DEFAULT 0,
  `time_created`  INTEGER DEFAULT 0
);

Cancel a task

FlutterDownloader.cancel(taskId: taskId);

Cancel all tasks

FlutterDownloader.cancelAll();

Pause a task

FlutterDownloader.pause(taskId: taskId);

Resume a task

FlutterDownloader.resume(taskId: taskId);

resume() will return a new taskId corresponding to a new background task that is created to continue the download process. You should replace the old taskId (that has paused status) by the new taskId to continue tracking the download progress.

Retry a failed task

FlutterDownloader.retry(taskId: taskId);

retry() will return a new taskId (just like resume())

Remove a task

FlutterDownloader.remove(taskId: taskId, shouldDeleteContent:false);

Open and preview a downloaded file

FlutterDownloader.open(taskId: taskId);

On Android, you can only open a downloaded file if it is placed in the external storage and there's at least one application that can read that file type on your device.

Bugs/Requests

Feel free to open an issue if you encounter any problems or think that the plugin is missing some feature.

Pull request are also very welcome!

More Repositories

1

flutter_launcher_icons

Flutter Launcher Icons - A package which simplifies the task of updating your Flutter app's launcher icon. Fully flexible, allowing you to choose what platform you wish to update the launcher icon for and if you want, the option to keep your old launcher icon in case you want to revert back sometime in the future. Maintainer: @MarkOSullivan94
Dart
1,921
star
2

chewie

The video player for Flutter with a heart of gold
Dart
1,873
star
3

community

Flutter Community - A central place for community made Flutter content.
1,505
star
4

flutter_webview_plugin

Community WebView Plugin - Allows Flutter to communicate with a native WebView.
Java
1,472
star
5

plus_plugins

Flutter Community Plus Plugins
Dart
1,441
star
6

get_it

Get It - Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App. Maintainer: @escamoteur
Dart
1,245
star
7

flutter_sticky_headers

Flutter Sticky Headers - Lets you place "sticky headers" into any scrollable content in your Flutter app. No special wrappers or magic required. Maintainer: @slightfoot
Dart
1,060
star
8

font_awesome_flutter

The Font Awesome Icon pack available as Flutter Icons
Dart
812
star
9

flutter_workmanager

A Flutter plugin which allows you to execute code in the background on Android and iOS.
Dart
802
star
10

redux.dart

Redux for Dart
Dart
514
star
11

flutter_blurhash

Compact representation of a placeholder for an image. Encode a blurry image under 30 caracters for instant display like used by Medium. Maintainer: @Solido
Dart
486
star
12

flutter_after_layout

Flutter After Layout - Brings functionality to execute code after the first layout of a widget has been performed, i.e. after the first frame has been displayed. Maintainer: @slightfoot
Dart
462
star
13

flutter-draggable-scrollbar

Draggable Scrollbar - A scrollbar that can be dragged for quickly navigation through a vertical list. Additional option is showing label next to scrollthumb with information about current item. Maintainer: @marica27
Dart
440
star
14

responsive_scaffold

Responsive Scaffold - On mobile it shows a list and pushes to details and on tablet it shows the List and the selected item. Maintainer: @rodydavis
Dart
359
star
15

app_review

App Review - Request and Write Reviews and Open Store Listing for Android and iOS in Flutter. Maintainer: @rodydavis
Dart
314
star
16

flutter_infinite_listview

Flutter Infinite ListView - ListView with items that can be scrolled infinitely in both directions. Maintainer: @slightfoot
Dart
305
star
17

backdrop

Backdrop implementation in flutter.
Dart
305
star
18

flutter_google_places

Google Places - Google places autocomplete widgets for flutter. No wrapper, use https://pub.dev/packages/google_maps_webservice. Maintainer: @juliansteenbakker
Dart
294
star
19

flutter_sms

A Flutter plugin to Send SMS and MMS on iOS and Android. If iMessage is enabled it will send as iMessage on iOS. This plugin must be tested on a real device on iOS. Maintainer: @rodydavis
Dart
232
star
20

flutter_uploader

background upload plugin for flutter
Dart
197
star
21

page_turn

Page Turn Widget - Add a page turn effect to widgets in your app. Maintainer: @rodydavis
Dart
191
star
22

import_sorter

🎯 Automatically organize your dart imports. Maintainer: @gleich
Dart
155
star
23

flutter_contacts

Contacts Service - A Flutter plugin to retrieve and manage contacts on Android and iOS devices. Maintainer: @lukasgit
Java
151
star
24

rx_command

RxCommand - Reactive event handler wrapper class inspired by ReactiveUI. Maintainer @escamoteur
Dart
134
star
25

flutter_wear_plugin

A plugin that offers widgets for Wear OS by Google
Dart
133
star
26

breakpoint

Breakpoint - A Flutter plugin to calculate the material design breakpoints. Maintainer: @rodydavis
Dart
108
star
27

get_version

Get Version - Get the Version Name, Version Code, Platform and OS Version, and App ID on iOS and Android. Maintainer: @rodydavis
Ruby
94
star
28

native_widgets

Native Widgets - A new Flutter package for using Android and iOS natively on each platform. Maintainer: @rodydavis
Dart
92
star
29

state_persistence

State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot
Dart
73
star
30

persist_theme

Persist Theme - A flutter plugin for persisting the theme data. Support for Dark Modes. Maintainer @rodydavis
Dart
68
star
31

dart_sealed_unions

Sealed Unions for Dart. Maintainer: @nodinosaur
Dart
65
star
32

flutter-styleguide

Flutter Style Guide. Suggested styles and best practices for teams using Flutter.
49
star
33

firestore_helpers

Firestore Helpers - Firestore helper function to create dynamic and location based queries. Maintainer: @escamoteur
Dart
48
star
34

wakelock_plus

Flutter plugin that allows you to keep the device screen awake on Android, iOS, macOS, Windows, Linux, and web.
Dart
45
star
35

rocket_guide

An example project for #30DaysOfFlutter.
Dart
33
star
36

android_id

Maintainer: @nohli
Dart
30
star
37

admin_dashboard

Admin Dashboard - a Flutter Community Dashboard that assists admins by rounding up and providing the admins with information regarding issues, latest activities on repositories, maintainers, level of access and a trigger to build and deploy to pub. dev, and more. (Work In Progress)
Dart
23
star
38

arcgis_map_sdk

Flutter implementation of the ArcGis map framework by esri
Dart
10
star
39

redux_undo

Redux Undo - Make your redux store undo- and redoable. Inspired by the JS redux_undo package. Maintainer: @michelengelen
Dart
5
star
40

site

Website
Dart
4
star
41

transfer-guide

The official Flutter Community Transfer Guide for package maintainers wanting to transfer their package to the organization.
4
star
42

interval_tree

A non-overlapping interval tree for Dart
Dart
3
star
43

readme_generator

A Dart program that generates the README.md for the FlutterCommunity/community repo.
Dart
3
star
44

fluttercommunity.github.io

The Flutter Community website.
HTML
1
star