Renewing a licence
The application needs to renew a licence, pre-emptively or already expired, to continue playback of the offline content.
The offline-license-renewal (or Offline License Renewal of UnifiedExampleCode) example application demonstrates how to listen for a licence expiry error and consequently renew the licence.
The drm-token-passing (DRM Token Passing of UnifiedExampleCode) example application demonstrates decoding a token, which enables discovery of the licence duration.
Licence renewal can be split into two stages: Expiry discovery and Renewal.
Expiry discovery
There are two routes to finding out when a licence will expire and require renewal.
Getting the licence duration
There is no generic API in Player SDK to return the licence expiry value as Apple does not expose it. How the licence expiry information is obtained depends on which FairPlay server the client is using.
The application can get the licence information by calling FairPlay server API or parsing the DRM data associated with the stream.
If a MediaLive/SDP server is used as the FairPlay server, see the Get license information from MediaLive Multidrm server page for licence expiry.
If using the SSP headend, the JWT token will have 'start', 'end' and 'duration' keys in the
contentsRights
dictionary. An example of how to obtain thecontentRights
is in the drm-token-passing example application.If not using the SSP headend, it is expected you already know how to obtain the licence duration.
With the duration, your application can determine when to request a licence renewal. This method allows an application to pre-emptively request one or more licences that are about to expire.
Licence error notification containing an expired lease message
This requires setting a listener for the OTVDRMLicenseError
notification. On receipt of the notification, if the notification object equals .keyResponseWithExpiredLease
, your application must renew the licence 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
Two methods of licence renewal are available. While both have the same result, the DRMManager
method may be used before you have a persistent asset and 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 licence delegate set up with a token.Call
renewLicense
on theDRMManger
, 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 the correct token.
Call
persistenceAsset renewLicense
method, passing thelicenseDelegate
.
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)