6. DRM License Renewal
This document is a machine-translated draft and is currently undergoing review. Some content may be inaccurate or differ from the original Korean version. For the most precise information, refer to the Korean documentation.
This document explains how to determine whether downloaded content stored in offline storage has an expired DRM license, and how to safely renew expired licenses in real time or in bulk.
All example code in this document is based on the official sample app kollus_player_ios.
Check license expiration
This is the reference code for checking the DRM expiration state of a content object in advance to determine whether to initiate the renewal process.
func isExpired(_ c: KollusContent) -> Bool {
return c.DRMExpired
|| (c.drmTotalExpirePlayTime > 0 && c.DRMExpirePlayTime <= 0)
|| (c.drmExpireCountMax > 0 && c.drmExpireCount <= 0)
}
Bulk license renewal API
Using the updateDownloadDRMInfo method, you can renew the DRM licenses of all content registered in storage at once.
func renewDRMContents(isAll: Bool) {
storage.updateDownloadDRMInfo(isAll)
}
Parameter specifications
| Parameter | Description |
|---|---|
isAll = true | Attempts to renew the licenses of all downloaded content registered in the SDK. |
isAll = false | Selects only content that has expired or is about to expire and attempts renewal. |
When the method is called, the overall progress status — including which item is currently being processed — is notified to the application layer through the injected delegate callback loop (kollusStorage(_:cur:count:error:)).
Background renewal limitations
iOS has strict Background Execution Limits, making it impossible to guarantee that license renewal will complete successfully while the app is in the background. The following patterns are recommended for stable integration.
- Use the foreground transition point: Call the API at the
applicationDidBecomeActiveentry point, which is when the user re-launches or activates the app. - Use the pre-playback timing: The most reliable and stable approach is to call the API synchronously (Sync) just before the user plays downloaded content.
While it is technically possible to register a periodic background task using the BGTaskScheduler component, the exact execution time is not guaranteed due to the nature of the iOS operating system.
Also note that the storage.setBackgroundDownload(true) setting is only an option to keep pure file download tasks running in the background, and does not guarantee background execution for the license exchange and renewal process.
---## Auto-renewal after network recovery
The official sample app does not include built-in logic for automatic license renewal upon network recovery. When developing a production service, it is recommended to implement exception handling code following the flow below.
- Use
NWPathMonitor, an Apple system framework, to detect network recovery timing on the device in real time. - When the user taps the play button in the offline library, run the expiration check function for the target content.
- If expiration is confirmed, immediately call
updateDownloadDRMInfo(false)synchronously to complete the license renewal before starting playback.
Exception handling for license renewal failure
If license renewal ultimately fails due to a server error or network interruption, the SDK notifies the exception through one of the following two methods in the injected delegate protocol.
func kollusStorage(_ storage: KollusStorage,
request: [AnyHashable: Any],
json: [AnyHashable: Any]?,
error: Error?) {
if let error = error {
// Renewal failed or forced expiration
}
}
func kollusStorage(_ storage: KollusStorage,
cur: Int32, count: Int32,
error: Error?) {
// Error occurred during bulk renewal; the affected item failed
}
When a license renewal failure signal is detected, display an exception message on screen such as "License renewal failed. Please check your network connection or re-download the content.", and provide UI branches for Retry / Re-download / Customer Support according to the user's choice. For information on the specific callback types, refer to the 8. Download Events/Callbacks document.