@@ -9,8 +9,6 @@ import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
9
9
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
10
10
import android.net.NetworkCapabilities.TRANSPORT_WIFI
11
11
import android.os.Build
12
- import android.provider.Settings.Secure
13
- import android.telephony.TelephonyManager
14
12
import com.segment.analytics.kotlin.core.Analytics
15
13
import com.segment.analytics.kotlin.core.BaseEvent
16
14
import com.segment.analytics.kotlin.core.Storage
@@ -25,6 +23,10 @@ import java.util.Locale
25
23
import java.util.TimeZone
26
24
import java.util.UUID
27
25
import java.lang.System as JavaSystem
26
+ import android.media.MediaDrm
27
+ import java.lang.Exception
28
+ import java.security.MessageDigest
29
+
28
30
29
31
// Plugin that applies context related changes. Auto-added to system on build
30
32
class AndroidContextPlugin : Plugin {
@@ -122,53 +124,23 @@ class AndroidContextPlugin : Plugin {
122
124
}
123
125
124
126
device = buildJsonObject {
125
- put(DEVICE_ID_KEY , getDeviceId(collectDeviceId, context ))
127
+ put(DEVICE_ID_KEY , getDeviceId(collectDeviceId))
126
128
put(DEVICE_MANUFACTURER_KEY , Build .MANUFACTURER )
127
129
put(DEVICE_MODEL_KEY , Build .MODEL )
128
130
put(DEVICE_NAME_KEY , Build .DEVICE )
129
131
put(DEVICE_TYPE_KEY , " android" )
130
132
}
131
133
}
132
134
133
- @SuppressLint(" HardwareIds" , " MissingPermission" )
134
- internal fun getDeviceId (collectDeviceId : Boolean , context : Context ): String {
135
+ internal fun getDeviceId (collectDeviceId : Boolean ): String {
135
136
if (! collectDeviceId) {
136
137
return storage.read(Storage .Constants .AnonymousId ) ? : " "
137
138
}
138
- val androidId = Secure .getString(context.contentResolver, Secure .ANDROID_ID )
139
- if (! androidId.isNullOrEmpty() && " unknown" != androidId) {
140
- return androidId
141
- }
142
-
143
- // Serial number, guaranteed to be on all non phones in 2.3+.
144
- val buildNumber = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
145
- Build .getSerial()
146
- } else {
147
- @Suppress(" DEPRECATION" )
148
- Build .SERIAL
149
- }
150
139
151
- if (! buildNumber.isNullOrEmpty()) {
152
- return buildNumber
153
- }
154
-
155
- // Telephony ID, guaranteed to be on all phones, requires READ_PHONE_STATE permission
156
- if (hasPermission(context, permission.READ_PHONE_STATE )
157
- && hasFeature(context, PackageManager .FEATURE_TELEPHONY )
158
- ) {
159
- val telephonyManager =
160
- getSystemService<TelephonyManager >(
161
- context,
162
- Context .TELEPHONY_SERVICE
163
- )
164
- val telephonyId = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
165
- telephonyManager.imei
166
- } else @Suppress(" DEPRECATION" ) {
167
- telephonyManager.deviceId
168
- }
169
- if (! telephonyId.isNullOrEmpty()) {
170
- return telephonyId
171
- }
140
+ // unique id generated from DRM API
141
+ val uniqueId = getUniqueID()
142
+ if (! uniqueId.isNullOrEmpty()) {
143
+ return uniqueId
172
144
}
173
145
// If this still fails, generate random identifier that does not persist across
174
146
// installations
@@ -270,4 +242,35 @@ fun hasPermission(context: Context, permission: String): Boolean {
270
242
/* * Returns true if the application has the given feature. */
271
243
fun hasFeature (context : Context , feature : String ): Boolean {
272
244
return context.packageManager.hasSystemFeature(feature)
273
- }
245
+ }
246
+
247
+
248
+ /* *
249
+ * Workaround for not able to get device id on Android 10 or above using DRM API
250
+ * {@see https://stackoverflow.com/questions/58103580/android-10-imei-no-longer-available-on-api-29-looking-for-alternatives}
251
+ * {@see https://developer.android.com/training/articles/user-data-ids}
252
+ */
253
+ fun getUniqueID (): String? {
254
+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .JELLY_BEAN_MR2 )
255
+ return null
256
+
257
+ val WIDEVINE_UUID = UUID (- 0x121074568629b532L , - 0x5c37d8232ae2de13L )
258
+ var wvDrm: MediaDrm ? = null
259
+ try {
260
+ wvDrm = MediaDrm (WIDEVINE_UUID )
261
+ val wideVineId = wvDrm.getPropertyByteArray(MediaDrm .PROPERTY_DEVICE_UNIQUE_ID )
262
+ val md = MessageDigest .getInstance(" SHA-256" )
263
+ md.update(wideVineId)
264
+ return md.digest().toHexString()
265
+ } catch (e: Exception ) {
266
+ return null
267
+ } finally {
268
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P ) {
269
+ wvDrm?.close()
270
+ } else {
271
+ wvDrm?.release()
272
+ }
273
+ }
274
+ }
275
+
276
+ fun ByteArray.toHexString () = joinToString(" " ) { " %02x" .format(it) }
0 commit comments