MarshMallow 警告“不建议获取设备标识符”后的唯一 Android 设备 ID?

Posted

技术标签:

【中文标题】MarshMallow 警告“不建议获取设备标识符”后的唯一 Android 设备 ID?【英文标题】:Unique Android Device ID after MarshMallow warning "get device identifiers is not recommended"? 【发布时间】:2017-03-10 01:38:31 【问题描述】:

我看到了我最好的问题之一Is there a unique Android device ID?

编辑:

我也需要适用于 Android 10 的解决方案。

我使用以下代码来获取唯一 ID。

public static String getDeviceId(Activity context) 

    PermissionsChecker checker = new PermissionsChecker(context);

    if (checker.lacksPermissions(Manifest.permission.READ_PHONE_STATE))
        PermissionsActivity.startActivityForResult(context, 0, REQUIRED_PERMISSION);
    else 
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

        final String tmDevice = tm.getDeviceId();
        final String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);

        UUID deviceUuid = new UUID(androidId.hashCode(), ((long) tmDevice.hashCode() << 32));

        return deviceUuid.toString();
    
    return null;

但我在悬停时收到一些警告

tm.getDeviceId();

Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 如下:

不建议使用 getString 获取设备标识符。

不建议使用设备标识符,除非是为了高价值 欺诈预防和高级电话用例。用于广告 用例,使用AdvertisingIdClient$Info#getId,对于分析,使用 InstanceId#getId.

有什么解决办法吗?它是有害的还是其他什么?

【问题讨论】:

您可以使用 IMEI 号码作为唯一标识符。这只是警告,因为现在黑客根手机并更改设备ID。 恢复出厂后会有变化。我不想要那个。 不,IMEI无论如何都不会改变。 根据我的经验...总是最好生成唯一的服务器密钥,而不是依赖于应用程序(如果您正在使用它) 看这里,可能对你有帮助:developer.android.com/training/articles/… 【参考方案1】:

非常简单的答案是,如果您需要唯一标识应用的每个用户,请在首次使用时创建一个随机 id。

    UUID.randomUUID().toString()

您可以将其保存在SharedPreferences 中,简单的工作就完成了。无需权限

问题是如果用户卸载并重新安装应用程序,它不会帮助你。

在 android 10 之前可以做到的一个简单技巧(根据 google,在 android 11 上不再可能)是将其保存在外部存储中的隐藏文件中......

然后在第一次使用应用程序时查找此类文件,如果存在读取 UUID,则不生成新文件并保存文件。

这个策略的问题是你需要WRITE_EXTERNAL_STORAGEPERMISSION

万一这不是问题,简单做...

new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + ".my_hidden_folder").mkdir();

保存在此文件夹中的任何文件都将对用户隐藏,在卸载您的应用时不会被删除

我个人使用

Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

这无害,只是谷歌不喜欢你这样做

【讨论】:

【参考方案2】:

这是在 Andorid Q 中添加的限制,getDeviceId 仅适用于系统应用程序。如果您尝试使用它会抛出异常

SecurityException: getDeviceId: The user 10196 does not meet the requirements to access device identifiers.

您可以从此link阅读更多 Andorid Q 更改

无论如何,在搜索并查看了许多解决方案后,我发现这个适用于每个 Android 以获得 UUID 的解决方案效果很好。

//This method is fully compatible with Android 1 to Android 10
public static String getDeviceUUID(Context context) 
    String serial = null;
    String m_szDevIDShort = "35" +
            Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
            Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
            Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
            Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
            Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
            Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
            Build.USER.length() % 10; //13 Bit
    try 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) 
            serial = android.os.Build.getSerial();
         else 
            serial = Build.SERIAL;
        
        //API>=9 Use serial number
        return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
     catch (Exception exception) 
        //serial Need an initialization
        serial = "serial"; // Random initialization
    
    // 15-digit number cobbled together using hardware information
    return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();

【讨论】:

【参考方案3】:

很久以前,我需要为每台设备设置一个持久的唯一 ID,但我遇到了同样的问题。 以下是我找到的解决方案:

    IMEI : 最差的解决方案:不带 SIM 卡的 Android 设备(例如许多平板电脑)被排除在外,您需要请求“拨打电话”权限才能获得它,这是没人愿意授予的。

    设备序列号:良好的解决方案,独特的价值;但在 API 级别 26 中已弃用 和新方法needs permission in Android 10.

    SSID(又名 Android_ID):我认为尽管有警告,但这是一个很好的解决方案。无重复记录。

一些半独特的解决方案包括:

Build.FINGERPRINT :构建的唯一记录。没有警告。它将设备限制在更小的范围内。

Build.TIME : 自生成设备 ROM 以来的时间(以毫秒为单位)。

提示:混合硬件属性是行不通的,因为它们可能相似(工厂生产大量模型),并且为了获得唯一 ID,您可能需要权限。 p>

提示 2:在设备内存中保存记录是浪费时间,因为总是可以更改/删除它们。

【讨论】:

【参考方案4】:

你无法真正“解决”这个警告。

但是,如果您愿意,可以通过添加 @SuppressLint("HardwareIds") 来禁用警告,这会解决这个问题。

请注意,通过此警告,Lint 让您有机会重新考虑是否需要发布。

【讨论】:

这是***.com/a/46321721/1318946的副本

以上是关于MarshMallow 警告“不建议获取设备标识符”后的唯一 Android 设备 ID?的主要内容,如果未能解决你的问题,请参考以下文章

Android 6编译环境搭建 (Marshmallow)

marshmallow: 简化Python对象系列化

python marshmallow库

HUST 1372 marshmallow

使用 Marshmallow 模式过滤 sqlalchemy 表更新

Android 6.0 (MarshMallow) 上的 HttpURLConnnection 请求失败