20

我看到了我最好的问题之一是否有唯一的 Android 设备 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.

有什么解决办法吗?是有害的还是别的什么?

4

4 回答 4

1

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

    UUID.randomUUID().toString()

你可以保存它,SharedPreferences简单的工作就完成了。无需权限

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

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

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

这个策略的问题是你需要WRITE_EXTERNAL_STORAGE许可

如果这不是一个简单的问题...

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

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

我个人使用

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

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

于 2020-03-16T13:21:31.863 回答
1

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

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

您可以从此链接阅读更多 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();
}
于 2020-03-22T01:42:34.203 回答
0

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

  1. IMEI : 最坏的解决方案: 很多平板电脑等没有 S​​IM 卡的 Android 设备被排除在外,您需要请求“拨打电话”权限才能获得它,这是没有人愿意授予的。

  2. 设备序列号:良好的解决方案,独特的价值;但在 API 级别 26 中已弃用,新方法需要在 Android 10 中获得许可。

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

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

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

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

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

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

于 2020-03-22T02:58:32.167 回答
-3

你不能真正“解决”这个警告。

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

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

于 2017-09-20T13:02:22.470 回答