Skip to main content

Download To Go

note

HLS/Fairplay Downloads feature is available from iOS 10.3+.

Download Manager

The DownloadManager singleton instance available with Quickplay Player library provides all download functionalities under one umbrella. One could fetch all downloads tasks as well as enqueue and purge download tasks.

Download Task

The DownloadTask with Quickplay Player library is analogous to a AVAssetDownloadTask on AVFoundation. A download task could be created and enqueued with download manager. Upon creating a download task, the task must be resumed to start download.

Download Task States

The following are the download task states

  • Suspended - while the task is paused, this is also the initial state
  • Running - while task is executing
  • Cancelled - while the task has been cancelled
  • Completed - while the task has completed
  • Failed - while the task has failed
  • Stale - while the task's asset has been deleted by OS or User

The download task exposes state and progress property which could be observed for state changes.

// Observing on download task's state property
downloadTask.state.add(self) { (oldValue, newValue) in
// handle state change
}

// Remove observers on download task complete, failed or Cancelled
downloadTask.state.remove(self)

Get All Download Tasks

To get all download tasks read allTasks property with DownloadManager . To get notified on task additions or removal, the same property can be observed for changes.

let allTasks = FLPlayerFactory.downloadManager.allTasks

Create Download Task

A download task can be created providing content id, name and preferrred bitrate for download. The contentId is to uniquely identify the download task and name is used to show the downloaded asset with the Settings app on iOS. Upon creating a download task, the task must be resumed to start download.

// Creating Player
if let contentURL = URL(string: contentUrl) {
let avURLAsset = AVURLAsset(url: contentURL)
// creating download request
let request = DownloadRequest(contentId: contentId,
contentUrl: avURLAsset.url,
title: name,
preferredVideoBitrate: 50_000)

// enqueue request
let downloadTaskResult = FLPlayerFactory.downloadManager.enqueue(request: request)
switch downloadTaskResult {
case let .success(downloadTask):
// resume task to start download
downloadTask.resume()
case let .failure(error):
// handle failure
}
}

Resume, Pause & Purge

When a download task has been created, it would be in suspended state. The same needs to be resumed to start the download. You could pause or cancel a running task. Purging a download task removes the download task as well its downloaded asset. Please note the persistent drm key if any associated with downloaded asset will not be deleted on purge of download task.

Download Progress

The progress of a download task could be tracked in two ways.

  • Observing on progress property of DownloadTask
  • Implementing DownloadManagerDelegate protocol to get notified on progress and state changes

Listening to Download Task Events

One could listen to download task state changes and downoad task delegate callbacks conforming to DownloadManagerDelegate protocol and setting the delegate with DownloadManager.

// yourController must conform to DownloadManagerDelegate protocol
FLPlayerFactory.downloadManager.delegate = yourController;

Offline Playback

To play a downloaded asset, read the avURLAsset property of the download task, which could be used with Player for playback. While playing fairplay protected downloaded asset, a dummy implementation of LicenseFetcherDelegate must be updated with LicenseFetcher to indicate that this content requires a persistent key for playback.

// Offline playback LicenseFetcherDelegate implementation
public class DownloadDelegate: FairplayLicenseFetcherDelegate {
public var skd: String
public var keyDeliveryType: KeyDeliveryType

init(skd: String, keyDeliveryType: KeyDeliveryType) {
self.skd = skd
self.keyDeliveryType = keyDeliveryType
}

public func didProvideApplicationCertificateRequest(for _: FairplayKeyLoadingRequest) {
// No-op
}

public func didProvideLicenseRequest(for _: FairplayKeyLoadingRequest, with _: Data, assetID _: String) {
// No-op
}
}

// delegate creation
let offlinePlaybackDelegate = DownloadDelegate(skd:"<SKD>", keyDeliveryType: .persistentStreamingKey)
// update this delegate instance with license fetcher prior to playback

Progressive Download

To play a downloading asset, use the AVURLAsset instance available with the download task to instantiate the player.

note

The download task would be paused on playback start. Similarly the task would be resumed automatically when playback stops.

Managing Persistent Keys for Asset

The license key for offline playback can be fetched and persisted using LicenseFetcher. It is suggested to persist the key prior to download of an asset. The key management is decoupled from downloaded asset, to facilitate manipulating (add, renew or delete) the keys independently. This is because technically a downloaded asset could be played using a valid key, irrespective of key being a persistent or on-demand key. Also, when a key expires, the asset need not be deleted and a new license could be fetched and persisted for the same asset.

if let contentURL = URL(string: playbackAsset.contentUrl) {
let avURLAsset = AVURLAsset(url: contentURL)

// Create License Fetcher Delegate for download
let delegate = FLPlayerFactory.fairplayLicenseFetcherDelegate(
applicationCertificate: appCert,
licenseUrl: licenseURL,
skd: skd,
keyDeliveryType: .download)

// Update License Fetcher to process persistent key fetching for an AVURLAsset
lf.updateLicenseFetcherDelegate(delegate, for: avURLAsset)

// Fetch persistent license
lf.fetchFairplayLicense(for: skd) { (result: Result<Void, Error>) in
switch result {
case .success:
// create download task and resume
case let .failure(error):
// handle failure
}
}
}

Download in Background

The application must include Background fetch capability to enable download in background. iOS allows download in background when app is backgrounded or suspended or terminated, but there are certain system limitations on recovery of downloads.

Downloads cannot be recovered in following cases:

  • Downloading with XCode Debugger attached
  • App killed by pressing home button and swipe up

Concurrent Downloads

There is no limitations on concurrent downloads. But please note the time for download completion depends on various factors like number of concurrent downloads, network bandwidth and bitrate of downloading content.