Android 10:IMEI在API 29上不再可用。寻找替代方案

时间:2019-09-25 17:19:02

标签: android api identifier imei

我们客户的应用程序主要功能是大量跟踪客户的设备,他们提供绑定到特定手机(而不是其所有者)的产品。使用设备imei可以做到这一点,但是随着Android 10中隐私权的更改,他们使其无法访问。 (https://developer.android.com/about/versions/10/privacy/changes)。

Android上有关于在特定用户情况下使用什么标识符的文档,但与我们的情况不符,因为我们需要它是唯一的,恒定的并绑定到设备(或至少很难更改)。 https://developer.android.com/training/articles/user-data-ids。 我正在考虑使用Android ID作为可能的解决方案,或者使用知道不可靠的Mac地址。

有什么想法吗?建议?经验?在这一点上,任何事情都可以作为选择

4 个答案:

答案 0 :(得分:13)

对于对@Sofien解决方案感兴趣的Java用户,我有:

  1. 将@Sofien的代码转换为Java,并进一步简化;
  2. 即使关注的是Android 10(API 29),也已在更多设备和操作系统版本上进行了广泛的测试。

1。代码和讨论

@Nullable
String getUniqueID() {
   UUID wideVineUuid = new UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L);
   try {
      MediaDrm wvDrm = new MediaDrm(wideVineUuid);
      byte[] wideVineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
      return Arrays.toString(wideVineId);
   } catch (Exception e) {
      // Inspect exception
      return null;
   }
   // Close resources with close() or release() depending on platform API
   // Use ARM on Android P platform or higher, where MediaDrm has the close() method
}

有两个主要区别@Sophien的代码。

  • 我没有使用MessageDigest,因此代码更简单。此外,MessageDigest.update()方法将SHA-256哈希函数应用于其参数,这导致丢失UUID唯一性的可能性极低。不对UUID进行散列的唯一缺点是您没有固定长度的UUID,而我在应用程序中对此并不关心。
  • 我使用的是toHexString,而不是Kotlin函数Arrays.toString(Java中没有单行对应的函数)。此选择是安全的,因为(A)它不会抛出Exception,并且(B)它会保留wideVineId及其String表示形式之间一一对应的关系。如果您希望坚持十六进制转换,则Apache Commons Codec库提供了单行解决方案,请参见this answer

当然,这些更改会导致产生不同的UUID,不必说其他选择也是可能的。还要注意,用Arrays.toString生成的UUID的格式为

[92, -72, 76, -100, 26, -86, 121, -57, 81, -83, -81, -26, -26, 3, -49, 97, -24, -86, 17, -106, 25, 102, 55, 37, 47, -5, 33, -78, 34, 121, -58, 109]

因此,如果您不想在UUID中使用特殊字符,则可以使用String.replaceAll()将其删除。

2。测试

我已经测试了UUID的持久性

  • 重新安装
  • 重新安装并重新启动

在以下设备/操作系统组合上:

  • 三星Galaxy S10 / API 29
  • 三星Galaxy S9 / API 29
  • 华为Nexus 6P / API 27(已通过出厂重置测试)
  • LG V20 / API 27(也经过了出厂重置测试)
  • 华硕ZenFone 2 / API 23
  • 三星Galaxy J5 / API 23
  • LG Nexus 5 / API 23
  • LG K4 / API 22
  • 三星Galaxy J3 / API 22
  • 三星Galaxy S4 / API 21

在所有测试中,targetSdkVersion是29。欢迎进行更多测试(尤其是在API 29上)。

答案 1 :(得分:2)

我建议您阅读google最佳实践的官方博客,以了解用例与您的规范相符的情况:https://developer.android.com/training/articles/user-data-ids.html

对我来说,我在android标识符的唯一性方面也遇到了同样的问题,我发现唯一的解决方案是使用MediaDrm API(https://android.googlesource.com/platform/frameworks/base/+/android-cts-4.4_r1/media/java/android/media/MediaDrm.java#539)  其中包含唯一的设备ID,即使在恢复出厂设置后也可以保留,并且无需对清单文件进行任何其他权限。

以下是几段代码,我们如何检索Android 10上的唯一标识符:

import android.media.MediaDrm
import java.security.MessageDigest
import java.util.*

object UniqueDeviceID {

    /**
     * UUID for the Widevine DRM scheme.
     * <p>
     * Widevine is supported on Android devices running Android 4.3 (API Level 18) and up.
     */
    fun getUniqueId(): String? {

        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) {
            //WIDEVINE is not available
            return null
        } finally {
            if (AndroidPlatformUtils.isAndroidTargetPieAndHigher()) {
                wvDrm?.close()
            } else {
                wvDrm?.release()
            }
        }
    }


    fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
}

答案 2 :(得分:1)

  1. 您可以通过gms服务访问android设备ID。参见下面的示例
> rep(k, each = 5)
 [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 
  1. 在设备首次启动时,将生成并存储一个随机值。可通过 Settings.Secure.ANDROID_ID 使用此值。这是一个64位数字,应在设备的整个使用寿命内保持不变。对于唯一的设备标识符,ANDROID_ID似乎是一个不错的选择,因为它可用于智能手机和平板电脑。要检索该值,可以使用以下代码,
private DeviceInfoProvider mDeviceInfo = new DeviceInfoProvider(Context)
String mDeviceId = DeviceInfoProvider.getDeviceId(Context);
Log.d("DEVICE_ID" , mDeviceId);

但是,如果在设备上执行了出厂重置,则该值可能会更改。制造商的流行手机中也存在一个已知错误,该错误中每个实例都具有相同的 ANDROID_ID 。显然,该解决方案并非100%可靠。

  1. 使用 UUID 。由于大多数应用程序的要求是识别特定的安装而不是物理设备,因此,如果使用UUID类,则为用户获取唯一ID的一种很好的解决方案。 Google的 Reto Meier Google I / O 演示文稿
  2. 中提出了以下解决方案
String androidId = Settings.Secure.getString(getContentResolver(),
                                             Settings.Secure.ANDROID_ID);

答案 3 :(得分:-5)

我已经在诺基亚手机中对其进行了测试,“在出厂重置时重置手机时,标识符已更改”。您是否在恢复出厂设置时对其进行了测试?