background_downloader 1.0.0 copy "background_downloader: ^1.0.0" to clipboard
background_downloader: ^1.0.0 copied to clipboard

outdated

A background file downloader for iOS and Android

A background file downloader for iOS and Android #

Define where to get your file from, where to store it, and how you want to monitor the download, and the background loader will ensure this is done in a responsible way using native platform background downloaders. background_downloader uses URLSessions on iOS and DownloadWorker on Android, so tasks will complete also when your app is in the background.

Concepts and basic usage #

A download is defined by a BackgroundDownloadTask object that contains the download instructions, and updates related to that task are passed on to callbacks that you need to register.

The DownloadStatusCallback receives the BackgroundDownloadTask and the updated DownloadTaskStatus, so a simple callback function is:

void downloadStatusCallback(
    BackgroundDownloadTask task, DownloadTaskStatus status) {
  print('downloadStatusCallback for $task with status $status');
}

The DownloadProgressCallback receives the BackgroundDownloadTask and progess as a double, so a simple callback function is:

void downloadProgressCallback(BackgroundDownloadTask task, double progress) {
  print('downloadProgressCallback for $task with progress $progress');
}

A basic file download with just status monitoring (no progress) then requires initialization to register the callback, and a call to enqueue to start the download:

  FileDownloader.initialize(downloadStatusCallback: downloadStatusCallback);
  final successFullyEnqueued = await FileDownloader.enqueue(
      BackgroundDownloadTask(url: 'https://google.com', filename: 'google.html'))

Note that success only refers to the enqueing of the download task, not its result, which must be monitored via the downloadStatusCallback. It will receive an update with status DownloadTaskStatus.running, followed by a status update with the result (e.g. DownloadTaskStatus.complete or DownloadTaskStatus.failed).

Location of the downloaded file #

The filename of the task refers to the filename without directory. To store the task in a specific directory, add the directory parameter to the task. That directory is relative to the base directory, so cannot start with a /. By default, the base directory is the directory returned by the call to getApplicationDocumentsDirectory(), but this can be changed by also passing a baseDirectory parameter (BaseDirectory.temporary for the directory returned by getTemporaryDirectory() and BaseDirectory.applicationSupport for the directory returned by getApplicationSupportDirectory() whis is only supported on iOS).

So, to store a file named 'testfile.txt' in the documents directory, subdirectory 'my/subdir', define the task as follows:

final task = BackgroundDownloadTask(
        url: 'https://google.com',
        filename: 'testfile.txt',
        directory: 'my/subdir');

To store that file in the temporary directory:

final task = BackgroundDownloadTask(
        url: 'https://google.com',
        filename: 'testfile.txt',
        directory: 'my/subdir',
        baseDirectory: BaseDirectory.temporary);

The downloader will only store the file upon success (so there will be no partial files saved), and if so, the destination is overwritten if it already exists, and all intermediate directories will be created if needed.

Note: the reason you cannot simply pass a full absolute directory path to the downloader is that the location of the app's documents directory may change between application starts (on iOS), and may therefore fail for downloads that complete while the app is suspended.

Monitoring progress while downloading #

To also monitor progress while the file is downloading, register the DownloadProgressCallback and add a progressUpdates parameter to the task:

    FileDownloader.initialize(
        downloadStatusCallback: downloadStatusCallback,
        downloadProgressCallback: downloadProgressCallback);
    final task = BackgroundDownloadTask(
        url: 'https://google.com',
        filename: 'google.html',
        progressUpdates:
            DownloadTaskProgressUpdates.statusChangeAndProgressUpdates);  // needed to also get progress updates
    final successFullyEnqueued = await FileDownloader.enqueue(task);

If a task completes successfully, the DownloadProgressCallback is called with a progress value of 1.0. Failed tasks generate progress of -1, cancelled tasks -2 and notFound tasks -3.

Because you can use the progress value to derive task status, you can choose to not receive status updates by setting the progressUpdates parameter of a task to DownloadTaskProgressUpdates.progressUpdates (and you won't need to register a DownloadStatusCallback). I fyou don't want to use any callbacks (and just check if the file exists after a while!) set the progressUpdates parameter of a task to DownloadTaskProgressUpdates.none.

Advanced use #

To manage or monitor tasks, use the following methods:

  • reset to reset the downloader by cancelling all ongoing download tasks
  • allTaskIds to get a list of taskId values of all tasks currently running (i.e. not completed in any way)
  • cancelTasksWithIds to cancel all tasks with a taskId in the provided list of taskIds
  • taskForId to get the BackgroundDownloadTask for the given taskId, or null if not found. Only tasks that are active (ie. not in final state) are guaranteed to be returned, but returning a task does not guarantee that it is active

Because an app may require different types of downloads, and handle those differently, you can specify a group with your task, and register callback specific to each group. If no group is specified (as in the examples above), the default group default is used. For example, to create and handle downloads for group 'bigFiles':

  FileDownloader.registerCallbacks(
        group: 'bigFiles'
        downloadStatusCallback: bigFilesDownloadStatusCallback,
        downloadProgressCallback: bigFilesDownloadProgressCallback);
  final task = BackgroundDownloadTask(
        group: 'bigFiles',
        url: 'https://google.com',
        filename: 'google.html',
        progressUpdates:
            DownloadTaskProgressUpdates.statusChangeAndProgressUpdates);
  final successFullyEnqueued = await FileDownloader.enqueue(task);

The methods reset and allTaskIds take a group parameter to get tasks in a specfic group. Note that if tasks are enqueued with a group other than default, calling reset or allTaskIds without a group parameter will not affect/include those tasks - only the default tasks.

Initial setup for iOS #

On iOS, ensure that you have the Background Fetch capability enabled:

  • Select the Runner target in XCode
  • Select the Signing & Capabilities tab
  • Click the + icon to add capabilities
  • Select 'Background Modes'
  • Tick the 'Background Fetch' mode

Note that iOS by default requires all URLs to be https (and not http). See here for more details and how to address issues.

No setup is required for Android

Limitations #

  • On Android, once started, a background download must complete within 8 minutes
  • On iOS, once enqueued, a background download must complete within 4 hours
  • On both platforms, downloads will not start without a network connection, and do not distinguish between metered (cellular) and unmetered (WiFi) connections
  • Redirects will be followed
  • Background downloads are aggressively controlled by the native platform. You should therefore always assume that a task that was started may not complete, and may disappear without providing any status or progress update to indicate why.
386
likes
0
points
65.9k
downloads

Publisher

verified publisherbbflight.com

Weekly Downloads

A background file downloader for iOS and Android

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, logging

More

Packages that depend on background_downloader