Renewing a licence
The application needs to renew a license, pre-emptively or already expired, to continue playback of the offline content.
The offline-license-renewal example application provides a complete example of how to listen for a license expiry error and consequently renew the license.
The drm-token-passing example application provides a complete example of decoding a token, which enables discovery of the license duration.
Expiry Discovery
License renewal can be split into two stages: Expiry Discovery and Renewal. There are two routes to finding out when a license will expire and require renewal.
Getting the License Duration
There is no generic API in Player SDK to return the license expiry value as Apple does not expose it. How the license expiry information is obtained depends on which FairPlay server the client is using.
The application can get the license information by calling FairPlay server API or parsing the drm data assoiciated with the stream.
- If a MediaLive/SDP server is used as the FairPlay server, please refer to the Get license information from MediaLive Multidrm server page for licence expiry.
- If using the SSP headend, the JWT token will have the 'start' and 'end' keys (as well as 'duration') in the contentsRights dictionary. An example of how to obtain the contentRights is in the 'drm-token-passing' example application.
- If not using the SSP headend, it is expected you already know how to obtain the license duration.
With the duration your application can determine when to request a license renewal. This method allows an application to pre-emptively request one or more licenses that are about to expire.
Licence error notification containing an expired lease message
Requires setting a listener for the OTVDRMLicenseError notification. On receipt of the notification, if the notification object equals .keyResponseWithExpiredLease, then your application must renew the license to continue playing the content.
NotificationCenter.default.addObserver(self, selector: #selector(self.licenseErrorNotification), name: .OTVDRMLicenseError,object: nil)
@objc func licenseErrorNotification(notification: NSNotification) {
let errorType = notification.object as? OTVDRMManager.OTVDRMLicenseError
if errorType == OTVDRMManager.OTVDRMLicenseError.keyResponseWithExpiredLease {
if let info = notification.userInfo as? [String: Any]{
keyIdentifier = info[OTVDRMManager.Keys.keyResponseWithExpiredLease] as? String ?? ""
// Renew the license with the identifier
)
}
}
}
Renewal
There are two methods of license renewal available. While both have the same end result, the DRMManager method may be used before we have a persistent asset and so allow a form of pre-delivery, whereas the requirement for a persistent asset for the second method renders it reactive.
OTVDRMManager
- Set up the license delegate
The DRMMAnager requires a license delegate set up with a token. - Call renewLicense on the DRMManger, passing the keyID and any required license options as parameters.
if let sspLicenseDelegate = licenseDelegate as? OTVSSPLicenseDelegate, let offlineURL = self.opyPersistenceAsset?.offlineURL() {
// The stream token is specific for OTVSSPLicenseDelegate, and it's different for each stream.
// Make sure set the stream token to license delgate before each playback/download.
sspLicenseDelegate.setStream(token: self.streamToken, with: offlineURL)
}
OTVDRMManager.shared.setLicenseDelegate(licenseDelegate)
let options = [OTVPersistenceManager.Keys.OTVLicenseOptionOffline: true as Any]
OTVDRMManager.shared.renewLicense(identifier: keyIdentifier, license: options)
OTVPersistenceAsset
- Get the correct persistence asset.
- Set up the license delegate with correct token.
- Call persistenceAsset renewLicense method, passing the licenseDelegate.
var asset: OTVPersistenceAsset? = {
let downloads = OTVPersistenceManager.shared.getDownloads()
for download in downloads {
let licenseDuration = download.licenseInfo?.duration
// Calculate and check if license gets expired, if yes return
return download
}
return nil
}()
if let sspLicenseDelegate = licenseDelegate as? OTVSSPLicenseDelegate, let offlineURL = self.opyPersistenceAsset?.offlineURL() {
// The token is specific for OTVSSPLicenseDelegate, and it's specific for each stream.
// Make sure set the stream token to license delgate before each renew license.
sspLicenseDelegate.setStream(token: self.streamToken, with: offlineURL)
}
asset?.renewLicense(delegate: licenseDelegate)