Skip to content
This repository has been archived by the owner on Jun 27, 2023. It is now read-only.

Commit

Permalink
fix: refactor getDeviceID to use DRM, remove AndroidID (segmentio#567)
Browse files Browse the repository at this point in the history
  • Loading branch information
oscb authored Jun 13, 2022
1 parent d1b6af1 commit f2616aa
Showing 1 changed file with 96 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.res.Resources
import android.media.MediaDrm
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.provider.Settings.Secure.getString
import android.util.Log
import androidx.core.content.pm.PackageInfoCompat
import com.facebook.react.ReactActivity
Expand All @@ -21,6 +20,8 @@ import com.facebook.react.module.annotations.ReactModule
import com.sovranreactnative.SovranModule
import java.lang.Exception
import java.util.*
import java.security.MessageDigest
import java.util.UUID


enum class ConnectionType {
Expand Down Expand Up @@ -54,88 +55,118 @@ class AnalyticsReactNativeModule : ReactContextBaseJavaModule, ActivityEventList
return PackageInfoCompat.getLongVersionCode(pInfo).toString()
}

@SuppressLint("HardwareIds")
private fun getUniqueId(collectDeviceId : Boolean): String? {
if (collectDeviceId) {
return getString(reactApplicationContext.contentResolver, Settings.Secure.ANDROID_ID)
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }

/**
* Workaround for not able to get device id on Android 10 or above using DRM API
* {@see https://stackoverflow.com/questions/58103580/android-10-imei-no-longer-available-on-api-29-looking-for-alternatives}
* {@see https://developer.android.com/training/articles/user-data-ids}
*/
private fun getUniqueId(collectDeviceId : Boolean): String? {
if (collectDeviceId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
return null

val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
var wvDrm: MediaDrm? = null
try {
wvDrm = MediaDrm(WIDEVINE_UUID)
val wideVineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)
val md = MessageDigest.getInstance("SHA-256")
md.update(wideVineId)
return md.digest().toHexString()
} catch (e: Exception) {
return null
} finally {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
wvDrm?.close()
} else {
wvDrm?.release()
}
}
return null
}
return null
}

private fun getConnectionType(context: Context): ConnectionType {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
var result: ConnectionType = ConnectionType.Unknown

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cm?.run {
cm.getNetworkCapabilities(cm.activeNetwork)?.run {
if (hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
result = ConnectionType.Wifi
} else if (hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
result = ConnectionType.Cellular
} else {
result = ConnectionType.Unknown
}
private fun getConnectionType(context: Context): ConnectionType {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
var result: ConnectionType = ConnectionType.Unknown

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cm?.run {
cm.getNetworkCapabilities(cm.activeNetwork)?.run {
if (hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
result = ConnectionType.Wifi
} else if (hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
result = ConnectionType.Cellular
} else {
result = ConnectionType.Unknown
}
}
} else {
cm?.run {
cm.activeNetworkInfo?.run {
if (type == ConnectivityManager.TYPE_WIFI) {
result = ConnectionType.Wifi
} else if (type == ConnectivityManager.TYPE_MOBILE) {
result = ConnectionType.Cellular
} else {
result = ConnectionType.Unknown
}
}
} else {
cm?.run {
cm.activeNetworkInfo?.run {
if (type == ConnectivityManager.TYPE_WIFI) {
result = ConnectionType.Wifi
} else if (type == ConnectivityManager.TYPE_MOBILE) {
result = ConnectionType.Cellular
} else {
result = ConnectionType.Unknown
}
}
}
return result
}
return result
}

@ReactMethod
fun getContextInfo(config: ReadableMap, promise: Promise) {
val appName: String = reactApplicationContext.applicationInfo.loadLabel(reactApplicationContext.packageManager).toString()
val appVersion: String = pInfo.versionName
val buildNumber = getBuildNumber()
val bundleId = reactApplicationContext.packageName
@ReactMethod
fun getContextInfo(config: ReadableMap, promise: Promise) {
val appName: String = reactApplicationContext.applicationInfo.loadLabel(reactApplicationContext.packageManager).toString()
val appVersion: String = pInfo.versionName
val buildNumber = getBuildNumber()
val bundleId = reactApplicationContext.packageName

val connectionType: ConnectionType = getConnectionType(reactApplicationContext)
val timezone: TimeZone = TimeZone.getDefault()
val currentLocale: Locale = Locale.getDefault()
val locale: String = "${currentLocale.language}-${currentLocale.country}"
val connectionType: ConnectionType = getConnectionType(reactApplicationContext)
val timezone: TimeZone = TimeZone.getDefault()
val currentLocale: Locale = Locale.getDefault()
val locale: String = "${currentLocale.language}-${currentLocale.country}"

val screenWidth = Resources.getSystem().displayMetrics.widthPixels
val screenHeight = Resources.getSystem().displayMetrics.heightPixels
val screenWidth = Resources.getSystem().displayMetrics.widthPixels
val screenHeight = Resources.getSystem().displayMetrics.heightPixels

val screenDensity = Resources.getSystem().displayMetrics.density;
val screenDensity = Resources.getSystem().displayMetrics.density;

val contextInfo: WritableMap = Arguments.createMap()
val contextInfo: WritableMap = Arguments.createMap()

contextInfo.putString("appName", appName)
contextInfo.putString("appVersion", appVersion)
contextInfo.putString("buildNumber", buildNumber)
contextInfo.putString("bundleId", bundleId)
contextInfo.putString("deviceId", getUniqueId(config.hasKey("collectDeviceId") && config.getBoolean("collectDeviceId")))
contextInfo.putString("deviceName", Build.DEVICE)
contextInfo.putString("deviceType", "android")
contextInfo.putString("manufacturer", Build.MANUFACTURER)
contextInfo.putString("model", Build.MODEL)
// generate random identifier that does not persist across installations
// use it as the fallback in case DRM API failed to generate one.
val fallbackDeviceId = UUID.randomUUID().toString()
val deviceId = getUniqueId(config.hasKey("collectDeviceId") && config.getBoolean("collectDeviceId"))?: fallbackDeviceId

contextInfo.putString("timezone", timezone.id)
contextInfo.putString("locale", locale)
contextInfo.putString("networkType", connectionType.toString().toLowerCase(currentLocale))
contextInfo.putString("appName", appName)
contextInfo.putString("appVersion", appVersion)
contextInfo.putString("buildNumber", buildNumber)
contextInfo.putString("bundleId", bundleId)
contextInfo.putString("deviceId", deviceId)
contextInfo.putString("deviceName", Build.DEVICE)
contextInfo.putString("deviceType", "android")
contextInfo.putString("manufacturer", Build.MANUFACTURER)
contextInfo.putString("model", Build.MODEL)

contextInfo.putString("osName", "Android")
contextInfo.putString("osVersion", Build.VERSION.RELEASE)
contextInfo.putString("timezone", timezone.id)
contextInfo.putString("locale", locale)
contextInfo.putString("networkType", connectionType.toString().toLowerCase(currentLocale))

contextInfo.putInt("screenWidth", screenWidth)
contextInfo.putInt("screenHeight", screenHeight)
contextInfo.putDouble("screenDensity", screenDensity.toDouble())
contextInfo.putString("osName", "Android")
contextInfo.putString("osVersion", Build.VERSION.RELEASE)

promise.resolve(contextInfo)
}
contextInfo.putInt("screenWidth", screenWidth)
contextInfo.putInt("screenHeight", screenHeight)
contextInfo.putDouble("screenDensity", screenDensity.toDouble())

promise.resolve(contextInfo)
}

fun getReferrer(activity: Activity): Uri? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
Expand Down

0 comments on commit f2616aa

Please sign in to comment.