Download to Go Integration Guide
Version: 18.4.1

Contents

1. Introduction

The Predictive Content Delivery (PCD) SDK allows users to download videos intelligently to mobile devices. Users initiate downloads by browsing your video catalog and selecting the content to watch.

A sophisticated Download Manager checks the battery, device storage, network, and other variables to make sure that the video transfer will succeed. Errors are thrown if the video transfer fails.

Downloads continue whether the app is active in the foreground, running in the background, or entirely closed. In addition, the SDK acts as a data cache, providing access to content along with its current download state.

1.1 Audience

This document is for developers implementing the PCD SDK; deep knowledge of Android and/or iOS is assumed.

There are separate instructions for Android and iOS. Configuring your project to support these platforms is covered in the following chapters.

2. Getting Started with iOS

Once you’ve downloaded the PCD SDK Zip file and adhere to the necessary requirements and dependencies, the fastest way to get started with the SDK is to try the sample app. After you’re done playing with the sample app, the next step is integrating the SDK in your app. These steps are covered in detail in Integrating With Your iOS Application.

2.1. Requirements and Dependencies

2.2. SDK Contents

When you download the PCD SDK zip, the contents include:

2.3. Trying the Sample App

The easiest way to get started is to try one of the sample apps.

  1. Open D2GExample app in the examples/ folder.
  2. Substitute your SDK license key instead of the "your_license_key_goes_here" value in the info.plist file.

Example:

<key>com.akamai</key>
	<dict>
            <key>vocsdk</key>
            <dict>
		<key>license</key>
		<string>your_license_key_goes_here</string>
            </dict>
	</dict>
  1. Open the VideosViewController in the D2GExample and update the on demand content details. This includes content ids to download and the provider name.
  2. Run the app.

3. Integrating With Your iOS Application

To start using the PCD SDK with your own app, you’ll need to include the SDK in your app.

3.1. Installing the iOS SDK - Use Cocoapods

Note: By default, Cocoapods installation works only for production integration. For trial SDK testing, refer section 3.2

The PCD SDK for iOS is available as a CocoaPods pod. CocoaPods is an open source dependency manager for Swift and Objective-C Cocoa projects. If you don’t already have the CocoaPods tool, install it by running the following command from the terminal.

sudo gem install cocoapods

Open the terminal and run pod init in your project directory. This will create a file named Podfile.

Edit Podfile and add the PCD SDK framework. Here is an example:

target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
    use_frameworks!
    pod 'AkamaiPCD'
end

Save the Podfile. Open a terminal and go to the directory containing the Podfile: Run the pod install command. This will install the APIs specified in the Podfile. Close Xcode, and then open (double-click) your project’s .xcworkspace file to launch Xcode. From this time onwards, you must use the .xcworkspace file to open the project.

3.2. Installing the iOS SDK - Manually

  1. Download the PCD SDK and unzip it in a folder under your project, e.g. ~/myproject/pcd_sdk.
  2. Locate VocSdk.framework FAT binary under ~/myproject/pcd_sdk/
  3. Click the project namein the Project navigator to open the project settings.
  4. In Project Settings, there are two panes. The first pane has the option to select Project and Targets. Choose your build target from Targets section..
  5. Select the General tab. Drag and drop the VocSdk.framework into Embedded Binaries section under the General tab.
  6. Remove VocSdk.framework reference in Linked frameworks and Libraries(if any).

3.2.1. Adding a Build Phase for FAT binary

When you attempt to submit your app to Apple’s App Store with FAT binary, it will be automatically rejected because the FAT binary has iPhone Simulator slices within it. For this reason, we supply an alternative script that will only include the binaries for the architectures that your build supports. The script will only process when the build configuration is for a Release build (e.g., when you archive a build).

  1. In Project Settings, choose your build target then click on Build Phases.
  2. Click the + and choose New Run Script Phase. This is to add a new build phase.
  3. Ensure this build phase occurs after the Embed Frameworks phase. By default, your new script will be the last step, and this is fine. Optionally single-click its name and rename it to strip_vocsdk.
  4. Click the arrow to expand the strip_vocsdk row.
  5. Leave the default shell setting of /bin/sh.
  6. The strip_vocsdk.sh script is packaged in the SDK zip file. Copy it into your project and add the path to it in the script area. The strip_vocsdk.sh path is relative to your .xcodeproj file and may need modification depending on where you saved it.

Note: This build phase is not needed if you have Cocoapods setup in your project.

3.3. Including the SDK

Import the VocSdk header in any class files where the SDK is required. Also define a single VocService object for your app. Create your VocService object in the app delegate to make the SDK available early in the app lifecycle and to simplify access to the VocService from other classes.

Example:

import <VocSdk/VocSdk.h>
@property (strong , nonatomic) id <VocService>  vocService;

3.4. Configuring App Transport Security

Starting in iOS 9.0, a new app security feature called App Transport Security (ATS) was introduced and is enabled by default. With ATS enabled, connections must use secure HTTPS instead of HTTP. Additionally, if the app contents that PCD SDK needs to download contain non-SSL items, those downloads will fail. Application developers must ensure that either

Navigate to info.plist file for the app. The optional ATS key to allow insecure (HTTP) content follows:

Example:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>pvoc-anaina.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

3.5. Adding License key

During initialization, the SDK will attempt to register using the license key. This key is linked to a content catalog, generation of usage statistics, and other SDK capabilities. In this guide, we are discussing the most common way of providing license key in your app. The other options of providing the license key in your app are discussed in the integration guide.

  1. Navigate to the Info.plist for the app.
  2. Create a new dictionary "vocsdk" within a "com.akamai" dictionary. If SDK finds "vocsdk" dictionary, it will be parsed for the "license" key, and if found, the value associated with that dictionary entry will be used as the license key for registration purposes.

Example:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>en</string>
    <key>CFBundleDisplayName</key>
    <string>PCDSdkExample</string>

    <!-- ... other Info.plist keys omitted ... -->

    <key>com.akamai</key>
    <dict>
            <key>vocsdk</key>
            <dict>
              <key>license</key>
              <string>your_license_key_goes_here</string>
            </dict>
    </dict>
</dict>
</plist>

3.6. Initialization

Initialization provides the client a running instance of the SDK service. Registration is a one-time event that occurs as part of initialization and activates the the SDK with a particular license key. The SDK is initialized by the VocServiceFactory call createServiceWithDelegate:delegateQueue:options:error:.

The recommended place for this is in AppDelegate’s application:didFinishLaunchingWithOptions:. The create call inputs a reference to the SDK delegate (see SDK Delegate) as well as a configuration options dictionary. The SDK delegate is the class you designate to respond to SDK activity.

The example below is inserted into AppDelegate.m. It initializes the SDK and tells it that AppDelegate will be the delegate to handle SDK messages.

Example:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSError *error = nil;
    self.vocService = [VocServiceFactory  createServiceWithDelegate:self
                       delegateQueue:[ NSOperationQueue  mainQueue ] options:nil
                       error:&error ];
    if (! self.vocService) {
        // error handling - could not start service
        return NO;
    }
    // app initialized
    return YES;
}

Once registration is successful, the SDK calls the didRegister: method on VocServiceDelegate. This can be used to report or log any problems starting the SDK. If registration fails due to a reason other than invalid credential, it will be retried a) On every 10 mins b) On network is available c) On app relaunch.

3.7. SDK Events

The SDK notifies your app of various events throughout its life cycle. Messages are sent asynchronously to an SDK delegate in your code that implements the VocServiceDelegate protocol. All of the delegate methods are optional.

- (void) vocService :(nonnull id<VocService>) vocService didBecomeNotRegistered :(nonnull NSDictionary *) info;
- (void) vocService :(nonnull id<VocService>) vocService didFailToRegister :(nonnull NSError *) error;
- (void) vocService :(nonnull id<VocService>) vocService didRegister :(nonnull NSDictionary *) info;
- (void) vocService :(nonnull id<VocService>) vocService itemsDiscovered :(nonnull NSArray *) items;
- (void) vocService :(nonnull id<VocService>) vocService itemsStartDownloading :(nonnull NSArray *) items;
- (void) vocService :(nonnull id<VocService>) vocService itemsDownloaded :(nonnull NSArray *) items;
- (void) vocService :(nonnull id<VocService>) vocService itemsEvicted :(nonnull NSArray *) items;
- (void) vocService :(nonnull id<VocService>) vocService hlsServerStarted:(nonnull NSURL*)url;
- (void) vocService :(nonnull id<VocService>) vocService hlsServerStopped:(nonnull NSURL*)url;

The SDK delegate is passed to the SDK in the initialization call. Typically, this is the app delegate since its lifetime will span that of the SDK, from registration until shutdown. Define your app delegate as follows to implement the SDK delegate protocol.

@interface AppDelegate : UIResponder < UIApplicationDelegate, VocServiceDelegate>

3.8. Enabing Background Execution

The PCD SDK downloads content while the application is running. Various factors determine when to start downloading, how much to download, and when to pause downloads. Influencing factors include the state of the mobile network and the quality state of the provider network.

When your app is in the foreground, downloads are happening without any need for changes in your code. However, in order to get best results, the PCD SDK should be able to download when your app is not in the foreground. In order to do that, you need to enable your app for background execution.

There are two types of background execution that the SDK uses to download content. Enable these two modes within the Xcode project settings, Capabilities tab, and Background Modes section:

To enable background fetch in the PCD SDK, you need to implement the system method UIApplicationDelegate application:performFetchWithCompletionHandler: and, from there, pass the message to the VocService by calling VocService application:performFetchWithCompletionHandler:

Here is what that looks like:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
    if (![ self.vocService application:application performFetchWithCompletionHandler:completionHandler ]) {
        completionHandler(UIBackgroundFetchResultNoData);
    }
}

3.9. Enabling Remote Notifications

To make remote notifications work in the PCD SDK you need to enable the SDK backend to send push notifications to your app, and make the supporting code changes.

4. Download to Go

The PCD SDK provides a number of ways to download content and Download to Go(D2G) is one such approach. D2G use case allows users to browse your video catalog and download one or more selections on to their mobile device. D2G approach is taken when the content downloaded is decided by the user and the SDK predictive caching is disabled. On registration of the SDK, the content metadata is not available locally. Each content is identified by a unique Content Id. The client can download the content based on this Content Id.

4.1. Setting up D2G

Before you can use D2G, you need to ingest your video catalog to the PCD Server. Ingesting content isn’t a self-service operation at this time, so talk to your Akamai representative about ingesting content. Each content( example a video) ingested is represented by a unique Content Id.

4.2. Configure SDK for D2G

VocService has a property, ‘config,’ which is an instance of VocConfig.h and provides a rich set of API to configure the SDK behavior. Default values for some of the configurations in VocConfig.h are set at the global level (set to server values) and you could override those at the client level. You should discuss with your Akamai representative about the default value preferences for the configurations such as permitted network types for download (wifi, cellular, or both), content items per category, daily download size limit, maximum size allowed per file download, permitted time of day for downloading, etc. Some of the mandatory configurations for D2G that needs to be set at the client level are the following. The client should setup these configurations right after the SDK initialization/registration.

4.2.1. Item Download Behavior

Most common D2G download behavior is to download no content unless requested explicitly by the user. The default behavior of the SDK is to preposition all the content from the content catalog. VocConfig has a property, itemDownloadBehavior, which provides the client an option to define the download behavior of the PCD SDK. For D2G use case, the behavior of the SDK needs to be set as no download(VOCItemDownloadNone). The other SDK download behaviors are auto download(VOCItemDownloadFullAuto) and download thumbnail files only(VOCItemDownloadThumbnailOnly).

Example:

self.vocService.config.itemDownloadBehavior = VOCItemDownloadNone ;

4.2.2. Auto Purge

The deletion of content in case of D2G is handled by the user. The default behavior of the SDK is to perform content purge based on certain device specific parameters. VocConfig has a property, enableAutoPurge, which provides the client an option to disable auto purge and the user will be responsible for the deletion of the content.

Example:

self.vocService.config.enableAutoPurge = NO ;

4.2.3. Maximum File Size

The D2G use cases generally have content that has large file size. The default max file size for which the SDK is allowed to download is 104 MB. VocConfig has a property, fileSizeMax, which provides the client an option to increase the max file size.

Example:

self.vocService.config.fileSizeMax = 10*1024*1024*1024 ;//(10 GB)

4.3. Initiating a Download

There are multiple ways you can initiate a content download. The simplest of all is to use VocService::downloadItemsWithContentIds:provider:options:.

WorkFlow

Example:

[appDelegate().vocService downloadItemsWithContentIds:@[@"contentId_1, contentId_2"]
provider:@"content_provider"
options:@{
                @"contentType":@(VOCItemTypeHLSVideo),
                @"downloadBehavior":@(VOCItemDownloadFullAuto),
                @"quality":@(VOCQualitySelectionMedium) }
completion:^(NSError*_Nullable error) {
                    if (error) {
                        //do something
                    }
        }];

4.4. Pause and Resume Downloading a Specific Item

The client can pause a specific content item download by making the VocService call pauseItemDownload: . VocItem has a readonly property, paused which the client can use to identify items that are paused. Alternatively, the same pause operation can be performed on one or more VocItems by making the VocService call pauseDownloadForItems:completion:. A paused download will not resume until a specific download request has been made.

Example: [appDelegate.vocService pauseItemDownload :vocItemVideo completion :^(NSError* _Nullable error) {}];

The client can resume the download of an item or items by making the VocService call downloadItems:.

Example: [appDelegate.vocService downloadItems:@[vocItemVideo] options:nil completion:^(NSError *_Nullable error) {}];

5. Access Content

Downloaded data includes three object types.

Data Object Description
Content A single video, song, HTML page, image, etc.
Category A named group of related content items (e.g., “Sports”).
Source Content providers configured at the Web portal. Every content item belongs to a source.

5.1. Accessing Content Items

The client can access VocItem using URL, unique ID and Content IDs.

API Description
getItemWithId:completion: Returns item available locally that has matching unique ID.
getItemsWithContentIds:sourceName:completion: Access item available locally that has matching content ID. If item is not available locally, the content metadata will be fetched from server and returns a newly created content item.
getItemWithURL:completion: Returns item available locally that has matching URL.

Example:

NSString *uniqueID = @"123456";
[appDelegate.vocService getItemWithId:uniqueID completion:^(NSError * __nullable error, id<VocItem>  __nullable item) {
	if (error || !item) {
		NSLog(@"Item unavailable.");
	}
	NSLog(@"Item '%@' share URL: %@", item.title, item.shareURL.absoluteString);
}

Also, the client can access items and videos using SDK Filter. Below are the APIs that are used for the same.

Object Type Class API Filter
VocItem VocDataQuery.h getItemsWithFilter:completion: VocItemFilter
VocItemVideo VocDataQuery.h getVideosWithFilter:completion: VocItemVideoFilter

Below are the SDK filters that can be used with above APIs.

Object Type Filter Protocol Available Filters
VocItem VocItemFilter allWithSort:
itemsInStates:sort:
itemsWithContentIds:sourceName:sortDescriptors:
itemsPartiallyDownloadedWithSort:
itemsDownloadingWithSort:
itemsFailedWithSort:
itemsPausedWithSort:
itemsIdleWithSort:
itemsQueuedWithSort:
itemsDiscoveredWithSort:
itemsDownloadedWithSort:
itemsWithCategory:sortDescriptors:
itemsDownloadedWithCategory:sortDescriptors:
itemsSavedWithSort:
itemsDownloadedNotViewedWithSort:
itemsInStates:withCategory:sortDescriptors:
itemsInStates:notViewedWithSort:
VocItemVideo (subset of Item) VocItemVideoFilter allWithSort:
videosInStates:sort:
videosPartiallyDownloadedWithSort:
videosDownloadingWithSort:
videosFailedWithSort:
videosPausedWithSort:
videosIdleWithSort:
videosQueuedWithSort:
videosDiscoveredWithSort:
videosDownloadedWithSort:
videosWithCategory:sortDescriptors:
videosDownloadedWithCategory:sortDescriptors:
videosSavedWithSort:
videosDownloadedNotViewedWithSort:
videosInStates:withCategory:sortDescriptors:
videosInStates:notViewedWithSort:

Most filters also accept an array of sort descriptors. The sort descriptor defines the order of those arrays. Pass a nil descriptor if order is unimportant.

In the example below, we used the “itemsInStates:sort:” filter to get a specific set of items whose state is VOCItemCached. Specific subsets can also be created by using alternative filters. These sets will behave as before, but will notify their listeners only when the filter is matched.

Example:

NSArray *sortDesc =   @[[[ NSSortDescriptor  alloc ] initWithKey:@"name"  ascending:YES selector:@selector(caseInsensitiveCompare:)]];

[appDelegate.vocService getItemsWithFilter:[VocItemFilter itemsInStates:[NSSet setWithArray:@[@(VOCItemCached)]] sort:sortDesc ] completion:^(NSError *__nullable error,  id <VocItemSet>  __nullable set) {
    // set.sources is ordered by each source's "name" property
}];

5.2. Listening for Data Set Changes

Data sets send notifications when items are added, changed, or removed. This is the best way to detect when individual items have finished downloading. To listen for object set changes a class must subscribe to the VocObjSetChangeListener protocol.

@interface MyClass() <VocObjSetChangeListener>

Setting the data set listener is done via addListener: and is demonstrated in the sections below for items. Listeners receive callbacks before and after any changes.

Example:

- (void) getContent
{
    [appDelegate.vocService getVideosWithFilter:[VocVideoFilter allWithSort:sortDesc] completion:^(NSError *__nullable error,  id <VocVideoSet>  __nullable set) {
        self.itemSet = itemSet;
        [self.itemSet addListener:self];
    }];
}

-(void) vocService:(nonnull id < VocService >)vocService objSetWillChange:(nonnull id < VocObjSet >) objSet added:(nonnull NSSet *) added updated:(nonnull NSSet *)updated removed:(nonnull NSSet *) removed objectsAfterChanges:(nonnull NSArray *)objectsAfterChanges
{
    if ([ objSet isEqual:self.itemSet ]) {
        NSLog(@"%ld items will change",   (unsigned long)updated.count);
    }
}

-(void)vocService:(nonnull id < VocService >)vocService objSetDidChange:(nonnull id < VocObjSet >)objSet
             added:(nonnull NSSet *)added updated:(nonnull NSSet *)updated removed:(nonnull NSSet *)removed
     objectsBefore:(nonnull NSArray *)objectsBefore
{
    if ([ objSet isEqual:self.itemSet ]) {
        NSLog(@"%ld items have changed",  (unsigned long)updated.count);
    }
}

5.3. Accessing Cached Content

5.3.1. Playing HLS Video Content

HTTP Live Streaming (HLS) video can be played from fully- or partially-downloaded content. Playback requires starting the SDK’s on-device HLS server. From that server, a playback link is then requested for the content.

The client starts the HLS server by calling VocService::startHLSServerWithCompletion:completion before playing the HLS content. The completion block is executed only after the HLS server is started. In the passed completion block, the client can access the HLS server URL and append to it the content item’s relative URL. Feed this URL to the media player to play the HLS content. Once playback is finished, stop the media server by calling VocService::stopHLSServer. The client controls the starting and stopping of the HLS server.

Example:

id<VocItemHLSVideo> hlsVideo = ...;

if (hlsVideo.state == VOCItemCached || hlsVideo.state == VOCItemPartiallyCached)  { //play from local cache
	[appDelegate.vocService startHLSServerWithCompletion:^(BOOL success) { //start the local HLS server
	    if (success) {
				//form local server video url
	        NSURL *url = [appDelegate.vocService.hlsServerUrl URLByAppendingPathComponent:hlsVideo.hlsServerRelativePath];
	        [self playVideo:url];
	    }
	}];
} else {
	[self playVideo:hlsVideo.file.url];//play from remote url
}

The SDK can be configured to preposition only the first n seconds of a HLS video. The number of seconds to be pre-cached can be configured thru PCD Portal > Device Profiles > Download Limits. Once this limit is set, the SDK will only download the set amount of content.

The procedure to play the content is the same as above. Once the recached section of the video is played, the rest of the content is streamed over the network.

5.3.2. Playing Cached Non-HLS Video

Clients can play content from a URL if the item is not yet cached, or from the local path if the item is cached.

Example to play a mp4 prepositioned video:

id<VocItemVideo> video =  ...;
NSURL   *url = video.file.url; //remote url
if (video.state == VOCItemCached || video.state == VOCItemPartiallyCached)  {
    url = [NSURL fileURLWithPath: video.localPath]; //local path
}

//Set the media player's content URL to this URL
[self playVideo:url];

5.3.3. Record Video Consumption by the User

When a user watches a video partially or fully, the client reports the consumption to the PCD SDK.

Example:

id<VocItemVideo> video =  ...;

// When user navigates back from the video player
// The total watched duration of the video
NSTimeInterval end = CMTimeGetSeconds(player.currentItem.currentTime);

// If playback did not start at the beginning put the position in start.
NSTimeInterval start = 0;
[video recordConsumption:[NSDate date] startingAt:start endingAt:end];

5.4. Content Item States

Each item progresses through different states before getting cached. VocItem has a state property which can take the following values.

VOCItemState Description
VOCItemMetadataNotReceived Item has been created locally. Waiting for metadata update from Server.
VOCItemDiscovered Item metadata has been received. Various device policies dictate whether the item gets queued for download.
VOCItemQueued Item has been added to downloading queue; it is currently not downloading. It will start downloading.
VOCItemDownloading Item is being downloaded.
VOCItemIdle Item is currently not downloading. Item has been previously queued for
downloading but did not finish. Download will resume automatically at some point.
Reason for stopping download can be found in VocItem::downloadError.
VOCItemPaused Item is currently not downloading. It has been explicitly paused with VocService pauseItems
VOCItemCached Item was downloaded successfully. Cached content is ready for use.
VOCItemPartiallyCached Item is configured for partial download. Requested part was download successfully. Cached content is ready for use.
VOCItemFailed If PCD SDK is unsuccessful to download any main content file after a number of attempts,
the item will be marked as failed and the downloaded content will be removed. No more download
attempts will be made on the item, unless an explicit download for this item is triggered again.
VocItem downloadError, can be used to verify the reason for download failure, error codes are provided
in the table below.
VOCItemDeleted Item has been deleted and cannot be used any more. There are no cached files.

5.5. Download Error Codes

The error codes for the SDK can be found in VOCSDKError enum. VocItem has a property downloadError and the valid error codes when item is in VOCItemFailed or VOCItemIdle states.

Error code Description
VocErrDownloadNoNetworkError Network is not available for download.
VocErrTimeOut Download was cancelled because it did not finish in the allocated time.
VocErrDownloadNetworkError Download failed due to invalid http response.
VocErrDownloadHttpError Download failed due to other http errors.
VocErrDownloadItemCorrupted Downloaded file cannot be parsed or cannot be accessed from/stored in the file system.
VocErrCancelled File download had to be interrupted because of item deletion, pause, no more background time
or download order optimizations.
VocErrDownloadFailed After a number of attempts the file cannot be downloaded due to unknown issue.

The valid error codes when item fails to sync metadata. The item will be in state VOCItemMetadataNotReceived.

Error code Description
VOCErrContentIdDoesNotExistInServer Item requested for download does not have metadata available in PCD Server.

Example:

switch(item.state) {
	case VOCItemIdle:
	case VOCItemFailed:
		switch(item.downloadError.code) {
			case VocErrDownloadNoNetworkError:
			case VocErrTimeOut:
			case VocErrDownloadNetworkError:
			case VocErrDownloadHttpError:
			case VocErrDownloadItemCorrupted:
			case VocErrCancelled:
				//handle
				break;
			default:
				break;
		}
		break;
	case VOCItemMetadataNotReceived:
		if(item.downloadError.code == VOCErrContentIdDoesNotExistInServer) {
			//handle
		}
		break;
	case VOCItemDiscovered:
	case VOCItemQueued:
	case VOCItemDownloading:
	case VOCItemPaused:
	case VOCItemCached:
	case VOCItemDeleted:
	case VOCItemPartiallyCached:
		break;
}

5.6. Content Sources

A content source identifies the provider (e.g., a channel, company, or aggregator) of content items. Sources are defined on the SDK Web portal. The SDK allows sources to be toggled on or off.

To track changes to a source set, subscribe your interface to the VocObjSetChangeListener protocol. Also define a property to reference the source set.

Example:

@interface   MyViewController () <VocObjSetChangeListener>
@property (strong, nonatomic)  id<VocSourceSet>  vocItemSourceSet;
@end

Create the source list in your implementation. This needs to be called only once per set, such as in -viewDidLoad for a view controller that uses sources.

Example:

[ vocService getSourcesWithFilter:[ VocItemSourceFilter allWithSort:nil ]
  completion:^(NSError *__nullable error,  id < VocSourceSet >  __nullable sourceSet) {
    if (error) {
        NSLog(@"Error getting sources: %@",  error);
        return;
    }
    self.vocItemSourceSet =  sourceSet;
    [ sourceSet addListener:self ];
}];

This will notify the listener when the set changes. You can also access individual sources by stepping through the source container, vocItemSourceSet.sources.

Example:

for (id < VocItemSource >  source  in   self.vocItemSourceSet.sources) {
    if (source.subscribed) {
        NSLog(@"Subscribed to %@",  source.displayName);
    }
}

5.7. Content Categories

Categories are named groups of related content, such as “family,” “trending,” or “news.” Working with a category makes it easy to display dedicated views for broad content types, or to toggle the display of an entire group.

To create and follow a category set, subscribe your interface to the VocObjSetChangeListener protocol (the same as for sources). Also define a property to reference the category set.

Example:

@interface   MyViewController() <VocObjSetChangeListener>
@property (strong,  nonatomic)  id<VocCategorySet> vocItemCategorySet;
@end

Create the category list in your implementation. This needs to be called only once per category set, such as in a view controller’s -viewDidLoad method. As shown for sources, this example adds our self object as a listener and retains a reference to the category set.

Example:

[ vocService getCategoriesWithFilter:[ VocItemCategoryFilter allWithSort:nil ]
  completion:^(NSError *__nullable error,  id < VocCategorySet >  __nullable categorySet) {
    if (error) {
        NSLog(@"Error getting categories: %@",  error);
        return;
    }

    self.vocItemCategorySet = categorySet;
    [ categorySet addListener:self ];
}];

Categories may be iterated over by using vocItemCategorySet.categories.

Example:

for (id < VocItemCategory >  category  in   self.vocItemCategorySet.categories) {
    if (category.subscribed) {
        NSLog(@"Subscribed category %@",  category.displayName);
    }
}

5.8. Source and Category Filters

Object Type Filter Protocol Available Filters
Source VocSourceFilter allWithSort:
Category VocItemCategoryFilter allWithSort: categoriesSelected: categoriesSelectedWithContent: subCategories: SearchField: suggestions:

Example:

NSArray *sortDesc =   @[[[ NSSortDescriptor  alloc ] initWithKey:@"name"  ascending:YES selector:@selector(caseInsensitiveCompare:)]];

[ vocService getSourcesWithFilter:[ VocItemSourceFilter allWithSort:sortDesc ] completion:^(NSError *__nullable error,  id < VocSourceSet >  __nullable set) {
    // set.sources is ordered by each source's "name" property
}];

Note: Any changes to VocSourceSet or VocCategorySet can be listened as well. Refer: 5.2. Listening for Data Set Changes

5.9. Accessing Subtitles and Thumbnails

The client can make VoItem call thumbnailsWithCompletion: to access a collection of thumbnail associated with the item. Similarly, the client can make VocItemVideo call subtitlesWithCompletion: to access a collection of subtitle associated with the item. The VocItem state is not affected by the download state of thumbnail or subtitle files. If autoDownload property for these files are set to YES, the file will get downloaded on the item download request.

Example:

[vocItemVideo subtitlesWithCompletion:^(NSSet<id<VocFile>>*  _Nullable subtitles) {
      	if (subtitles) {
           	for (id<VocFile> subtitle in subtitles) {
                 	if (!subtitle.autoDownload) {
                      	subtitle.autoDownload = YES;
                 	}
           	}
      	}
      	[appDelegate.vocService downloadItems:@[vocItemVideo] completion:nil];
 	}];

6. Managing Downloads

6.1. Track Progress of a Downloading Video

There are two properties in VocItem that will allow the client app to calculate download progresss.

The client app can listen for bytesDownloaded changes by subscribing to the VocObjSetChangeListener protocol (refer to Listening for Data Set Changes) or using key-value observing (KVO). Alternatively, the client app can use a timer to periodically poll bytesDownloaded and update the progress.

6.2. Delete and Lock

The SDK provides three delete options for each item:

API Functionality
VocItem::deleteItem: Deletes both the metadata and files associated with the item.
VocItem::deleteFiles: This is ideally used in Download to Go use case. It deletes just the files associated with the item. Since the metadata is not removed, the client can re-download the video at any point after deleting the files. Optionally, the app can retain the video’s thumbnail by setting deleteThumbnail parameter to NO.
VocService::deleteFilesForItems:options:completion: Deletes files associated with multiple items.

Note: Some content consumers exhibit unexpected behavior if the item gets deleted while it is consumed. The SDK doesn’t know whether the item is currently consumed unless it is notified explicitly. It is recommended to call VocItem::lock before the item gets consumed and VocItem::unlock after the consumption is completed.

6.3. Download Policy

Device policy are those configurations set on the SDK by the client and server. Based on device policy, the VocService boolean property downloadAllowed can be used to determine whether the SDK permits downloads at a given time. This is continuously updated as device conditions change, such as loss of network, the battery level dropping too low, or running out of drive space. To see the specific download status, access the VocService enumerated value VOCPolicyStatus. The status when downloads are allowed is VOCPolicyStatusInPolicy.


- (void)downloadItem {

if (!self.vocService.downloadAllowed) {
			switch(self.vocService.lastPolicyStatus) {
					//handle accordingly
				case VOCPolicyStatusNoDownload:
					break;
				case VOCPolicyStatusWifiDisallowedOnBattery:
					break;
				case VOCPolicyStatusWifiNotAllowed:
					break;
				case VOCPolicyStatusHostUnreachableViaWifi:
					break;
				case VOCPolicyStatusCellularDisallowedOnBattery:
					break;
				case VOCPolicyStatusCellularTimeOfDay:
					break;
				case VOCPolicyStatusCellularNotAllowed:
					break;
				case VOCPolicyStatusHostUnreachableViaCellular:
					break;
				case VOCPolicyStatusBatteryTooLow:
					break;
				case VOCPolicyStatusCacheIsFull:
					break;
				case VOCPolicyStatusNoFreeSpaceForCache:
					break;
				case VOCPolicyStatusDailyLimitReached:
					break;
			}
      return;
	}

//continue downloading by calling download API

}

When downloadAllowed is false, content item state will move to VOCItemIdle. In some use cases, the client need to identify the reason for not downloading and inform the user. This is in addition to VocItem::downloadError check.

Example:

if (video.state == VOCItemIdle) {}
  if(!appDelegate().vocService.downloadAllowed) {
  	switch(self.vocService.lastPolicyStatus) {
  					//handle accordingly
  		}
  }
  if (video.downloadError) {
    //handle accordingly
  }
}

6.4. Token Authentication

Some of the customer’s content is protected by a combination of time constrained tokens. There are long lived and short lived tokens. Some are part of the query string, some are cookies.

6.4.1. Assumptions

6.4.2. Workflow

Example:

- (void) vocService:(nonnull id<VocService>)vocService convertDownloadRequest:(nonnull NSMutableURLRequest*) request
  		item:(nonnull id<VocItem>)item
  		file:(nonnull id<VocFile>)file
completion:(nonnull void (^)(nullable NSMutableURLRequest *request))completion
{
  switch ([file.getFileType]) {
  	case VOCHLSMasterFile:
      //If you want to set a URL with new token auth for the main file
      //getAuthorizedUrlbytheClient is a method implemented by the client
      NSURL *url = [self getAuthorizedUrlbytheClient:item.contentId];
      [request setURL:url];
      //If you want to set the token through cookie
      [request addValue:@"abc=123;" forHTTPHeaderField:@"Set-Cookie"];
  		break;
  		default:
  			break;
  	}
  	completion(request);
  }

7. SDK Settings

7.1. Maximum File Size

Some providers have content that are large in file size. The default max file size for which the SDK is allowed to download is 104 MB. VocConfig has a property, fileSizeMax, which provides the client an option to increase the max file size.

Example:

self.vocService.config.fileSizeMax = 10*1024*1024*1024 ;//(10 GB)

7.2. Network Preference

The API provides control over whether downloads are permitted on wifi, cellular, or both. Setting the VocConfig networkSelection property affects downloads that have not already started.

Example:

self.vocService.config.networkSelection = VOCNetworkSelectionWifiAndCellular;

7.3. Maximum Number of Concurrent Downloads

The default behavior for the SDK is to perform any number of concurrent file downloads. VocConfig has a property, maxConcurrentDownloads, which provides the client an option to restrict the number of simultaneous downloads.

Example:

self.vocService.config.maxConcurrentDownloads = 2 ;

7.4. Maximum Cache size

The default cache size of the SDK is to 5 GB. VocService has a property, cacheSize, which provides the client an option to restrict the cache size.

Example:

self.vocService.cacheSize = 8 * 1024 * 1024 * 1024;//8GB