diff --git a/.gitignore b/.gitignore index a631cf7133..93f3e1038d 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ captures/ .idea/jarRepositories.xml .idea/misc.xml .idea/migrations.xml +.idea/markdown.xml # Android Studio 3 in .gitignore file. .idea/caches .idea/modules.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 306e0d6651..c3984c6f97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,12 @@ All notable changes to this project will be documented in this file. Take a look * New experimental positioning of EPUB decorations that places highlights behind text to improve legibility with opaque decorations (contributed by [@ddfreiling](https://github.com/readium/kotlin-toolkit/pull/721)). * To opt-in, initialize the `EpubNavigatorFragment.Configuration` object with `decorationTemplates = HtmlDecorationTemplates.defaultTemplates(alpha = 1.0, experimentalPositioning = true)`. +#### LCP + +* Added an initializer parameter for providing a custom device identifier (contributed by [@dewantawsif](https://github.com/readium/kotlin-toolkit/pull/720)). + * You must ensure the identifier is unique and stable for the device (persist and reuse across app launches). + * Recommended: generate an app-scoped UUID and store it securely. Avoid hardware or advertising identifiers. + ## [3.1.2] diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt index ad7f405b76..99d3f0f118 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt @@ -135,11 +135,15 @@ public interface LcpService { * @param deviceName Device name used when registering a license to an LSD server. * If not provided, the device name will be generated from the device's manufacturer and * model. + * @param deviceId Device ID used when registering a license to an LSD server. + * If not provided, the device ID will be generated as a random UUID and persisted for + * future sessions. */ public operator fun invoke( context: Context, assetRetriever: AssetRetriever, deviceName: String? = null, + deviceId: String? = null, ): LcpService? { if (!LcpClient.isAvailable()) { return null @@ -152,6 +156,7 @@ public interface LcpService { val network = NetworkService() val device = DeviceService( deviceName = deviceName, + deviceId = deviceId, repository = deviceRepository, network = network, context = context diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/service/DeviceService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/service/DeviceService.kt index c723f075e3..ee81cd5e93 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/service/DeviceService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/service/DeviceService.kt @@ -10,31 +10,34 @@ package org.readium.r2.lcp.service import android.content.Context -import android.content.SharedPreferences import android.os.Build -import java.io.Serializable +import androidx.core.content.edit import java.util.UUID import org.readium.r2.lcp.license.model.LicenseDocument import org.readium.r2.lcp.license.model.components.Link internal class DeviceService( deviceName: String?, + deviceId: String?, private val repository: DeviceRepository, private val network: NetworkService, val context: Context, -) : Serializable { - - private val preferences: SharedPreferences = context.getSharedPreferences( - "org.readium.r2.settings", - Context.MODE_PRIVATE - ) - - val id: String - get() { - val deviceId = preferences.getString("lcp_device_id", UUID.randomUUID().toString())!! - preferences.edit().putString("lcp_device_id", deviceId).apply() - return deviceId - } +) { + + val id: String = deviceId ?: generatedId + + private val generatedId: String get() { + val key = "lcp_device_id" + + val preferences = context.getSharedPreferences("org.readium.r2.settings", Context.MODE_PRIVATE) + + preferences.getString(key, null) + ?.let { return it } + + val id = UUID.randomUUID().toString() + preferences.edit { putString(key, id) } + return id + } val name: String = deviceName ?: "${Build.MANUFACTURER} ${Build.MODEL}"