Offline Playback

This tutorial will walk you through the facilities that the Bitmovin Player React Native SDK offers for working with offline content and offline playback.

Manage Offline Content For Playback

One of the challenges of enabling offline playback is downloading and managing assets. The Bitmovin SDK provides the ability to download content, as well as to pause, resume and cancel downloads. It also enables downloaded content to be deleted. These operations are provided via the OfflineContentManager API, which is responsible for managing the state of the assets.

Setup

Android

In order to use offline functionality, the following dependency must be added manually to the build.gradle file:

implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")

Additionally, the permission for checking the network state is required in the Android Manifest:

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

Depending on the location the offline data is saved, it may also be required to add the STORAGE permission to the Android Manifest:

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

iOS

In order to enable the Offline Feature in an iOS application, the following changes has to be made on the native side of the React Native application.

📘

Note

The Offline Feature is not available in iOS simulators due to missing support from Apple for downloading content in the simulator environments.

Initialize the OfflineManager

You first need to initialize the singleton class OfflineManager in your AppDelegate class. To do so, you add the following code snippet in the application(_:didFinishLaunchingWithOptions:) method:

OfflineManager.initializeOfflineManager()

App Lifecycle Support

In order to appropriately handle application lifecycle events, such as the application going into background, add the following code into application(_:handleEventsForBackgroundURLSession:completionHandler:) in your AppDelegate:

OfflineManager.sharedInstance().add(completionHandler: completionHandler, for: identifier)

API Usage

The core component responsible for handling offline content is the OfflineContentManager. It allows fetching the current offline state, managing offline content and requesting state changes.

OfflineContentManager

One OfflineContentManager is linked with one SourceConfig. When instantiating an OfflineContentManager, it is required to provide a unique ID for the content and the SourceConfig.

const offlineContentManager = new OfflineContentManager({
  identifier: '<UNIQUE-CONTENT-ID>',
  sourceConfig: sourceConfig,
});

OfflineContentManager has to be initialized before first interaction, using:

offlineContentManager
  .initialize()
  .then(() => console.log('Offline Content Manager is ready to use'));

OfflineContentManagerListener

Listeners can be added to OfflineContentManager via addListener API, which returns a function that removes this listener from the OfflineContentManager that registered it when called.

const removeOfflineContentManagerListener = offlineContentManager.addListener({
  onOptionsAvailable: (e) => console.log('Options available'),
  onProgress: (e) => console.log(`Progress: ${e.progress}`),
  onCompleted: (e) => console.log('Download has finished'),
  onError: (e) => console.log(`Error happened: ${e.message}`),
  onDrmLicenseUpdated: (e) => console.log('DRM license updated'),
  onDrmLicenseExpired: (e) => console.log('DRM license expired'),
  onResumed: (e) => console.log('Download resumed'),
  onSuspended: (e) => console.log('Download suspended'),
  onCanceled: (e) => console.log('Download canceled'),
});

// Call this to remove the listener:
removeOfflineContentManagerListener();

The OfflineContentManagerListener provides seven callbacks:

  • onOptionsAvailable is called after a getOptions call.
  • onProgress is called when the progress for an ongoing operation has changed, e.g. the download progress.
  • onCompleted is called when downloading has completed.
  • onError is called when an error occurs.
  • onDrmLicenseUpdated is called when the stored DRM license was updated.
  • onDrmLicenseExpired is called when the stored DRM license was updated. This is only supported on iOS.
  • onSuspended is called when download has been suspended.
  • onResumed is called when download has been resumed.
  • onCanceled is called when download has been canceled.

OfflineContentOptions

OfflineContentOptions can be received by calling getOptions on the OfflineContentManager. OfflineContentOptions represent the downloadable tracks for a stream with the available tracks for audio and captions/subtitles.

Downloading Content

Once an OfflineContentManger is created, downloading of content can be started. To gain knowledge of the available audio and subtitle tracks, getOptions should be called:

offlineContentManager.getOptions()

As this is an asynchronous call, the response must be handled in the OfflineContentManagerListener callback:

const removeOfflineContentManagerListener = offlineContentManager.addListener({
  onOptionsAvailable: (e) => {
    console.log('Options available');
    // Select desired tracks for download
  },
});

To start a download, first construct an OfflineDownloadRequest, using values from OfflineContentOptions then call offlineContentManager.download() with the request object.

const offlineOptions: OfflineContentOptions; // value from `onOptionsAvailable`
const downloadRequest: OfflineDownloadRequest = {
  minimumBitrate: 800000, // Download video with nearest higher available bitrate
  audioOptionIds: offlineOptions?.audioOptions.map((option) => option.id), // Download all audio tracks
  textOptionIds: offlineOptions?.textOptions.map((option) => option.id), // Download all text tracks
};
offlineContentManager.download(downloadRequest)

Download DRM protected content

For offline download and playback we support the same DRM solutions as presented in our related guide.

Playing Offline Content

In order to play the downloaded content, you only need to load the offline content into the player:

player.loadOfflineContent(offlineContentManager);

OfflineState

You can check the state of the download operation anytime by calling the OfflineContentManager's state() API, which is very useful for checking on the state of an asset before performing further actions. For example, checking the asset's offline state before updating the UI or allowing the user to cancel a download:

const offlineState = await offlineContentManager.state()
switch (offlineState) {
  case OfflineState.NotDownloaded:
    // Content is not downloaded
    break;
  case OfflineState.Downloading:
    // Content is currently downloading
    break;
  case OfflineState.Suspended:
    // Content download is suspended
    break;
  case OfflineState.Downloaded:
    // Content is downloaded
    break;
}

Summary

With the solutions mentioned in this guide you will be able to download, manage and play content without internet connection on your iOS and Android devices.

See OfflinePlayback.tsx for a full example implementation on how to use the Offline Feature.