@@ -30,27 +30,12 @@ open class AndroidContextPlugin : ContextPlugin() {
3030 }
3131
3232 /* *
33- * Generate a device ID using Android-specific logic.
34- * Priority: configuration -> store (if not forceNew) -> advertising ID -> app set ID -> random UUID
35- *
36- * @param forceNew If true, skip checking the store and generate a fresh deviceId
37- * @return the generated device ID (never null for Android)
33+ * Create a device ID from available sources.
34+ * Priority: advertising ID -> app set ID -> random UUID
3835 */
39- fun generateDeviceId ( forceNew : Boolean = false ): String {
36+ internal fun createDeviceId ( ): String {
4037 val configuration = amplitude.configuration as Configuration
4138
42- // Check configuration (always respected, even with forceNew)
43- configuration.deviceId?.let { return it }
44-
45- // Check store (skip if forcing new)
46- if (! forceNew) {
47- amplitude.store.deviceId?.let { deviceId ->
48- if (validDeviceId(deviceId) && ! deviceId.endsWith(" S" )) {
49- return deviceId
50- }
51- }
52- }
53-
5439 // Check advertising ID (if enabled and not per-install)
5540 if (! configuration.newDeviceIdPerInstall &&
5641 configuration.useAdvertisingIdForDeviceId &&
@@ -67,21 +52,25 @@ open class AndroidContextPlugin : ContextPlugin() {
6752 if (configuration.useAppSetIdForDeviceId) {
6853 contextProvider.appSetId?.let { appSetId ->
6954 if (validDeviceId(appSetId)) {
70- return " ${ appSetId} S "
55+ return " $appSetId$DEVICE_ID_SUFFIX_APP_SET_ID "
7156 }
7257 }
7358 }
7459
7560 // Generate random ID
76- return UUID .randomUUID().toString() + " R "
61+ return UUID .randomUUID().toString() + DEVICE_ID_SUFFIX_RANDOM
7762 }
7863
7964 @Deprecated(
8065 message = " Use generateDeviceId() instead. Amplitude now handles setting the deviceId." ,
8166 replaceWith = ReplaceWith (" generateDeviceId()" ),
8267 )
8368 fun initializeDeviceId (configuration : Configuration ) {
84- amplitude.setDeviceId(generateDeviceId(forceNew = false ))
69+ val deviceId =
70+ configuration.deviceId
71+ ? : amplitude.store.deviceId?.takeIf { validDeviceId(it, allowAppSetId = false ) }
72+ ? : createDeviceId()
73+ amplitude.setDeviceId(deviceId)
8574 }
8675
8776 @Deprecated(
@@ -187,11 +176,33 @@ open class AndroidContextPlugin : ContextPlugin() {
187176 const val PLATFORM = " Android"
188177 const val SDK_LIBRARY = " amplitude-analytics-android"
189178 const val SDK_VERSION = BuildConfig .AMPLITUDE_VERSION
179+
180+ /* *
181+ * Device ID suffix indicating the ID was derived from App Set ID.
182+ *
183+ * When a stored device ID ends with this suffix, [createDeviceId] will attempt
184+ * to regenerate it to potentially upgrade to a better identifier (e.g., advertising ID
185+ * if the user later grants permission).
186+ */
187+ private const val DEVICE_ID_SUFFIX_APP_SET_ID = " S"
188+
189+ /* *
190+ * Device ID suffix indicating the ID is a randomly generated UUID.
191+ */
192+ private const val DEVICE_ID_SUFFIX_RANDOM = " R"
193+
190194 private val INVALID_DEVICE_IDS =
191195 setOf (" " , " 9774d56d682e549c" , " unknown" , " 000000000000000" , " Android" , " DEFACE" , " 00000000-0000-0000-0000-000000000000" )
192196
193- fun validDeviceId (deviceId : String ): Boolean {
194- return ! (deviceId.isEmpty() || INVALID_DEVICE_IDS .contains(deviceId))
197+ fun validDeviceId (
198+ deviceId : String ,
199+ allowAppSetId : Boolean = true,
200+ ): Boolean {
201+ return when {
202+ deviceId.isEmpty() || INVALID_DEVICE_IDS .contains(deviceId) -> false
203+ ! allowAppSetId && deviceId.endsWith(DEVICE_ID_SUFFIX_APP_SET_ID ) -> false
204+ else -> true
205+ }
195206 }
196207 }
197208}
0 commit comments