马歇尔洛警告后如何获取唯一的安卓设备ID?

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

有解决方案吗?这会有害或其他什么后果吗?


2
您可以使用IMEI号作为唯一标识符。但是现在的黑客越来越猖獗,会对手机进行越狱并更改设备ID。这只是一个警告。 - rushank shah
不,IMEI在任何情况下都不会改变。 - rushank shah
2
根据我的经验,最好生成唯一的服务器密钥,而不是依赖于应用程序(如果您正在使用它)。 - H Raval
据我所知,ANDROID_ID在格式化和恢复出厂设置后会更改。 - nani
@rushankshah,IMEI号对于没有SIM卡的平板电脑是无效的。 - Pratik Butani
显示剩余3条评论
3个回答

1
非常简单的答案是,如果您需要唯一标识每个应用程序用户,请在首次使用时创建一个随机ID。
    UUID.randomUUID().toString()

您可以将其保存在SharedPreferences中,这样就完成了简单的工作。不需要权限。
问题是,如果用户卸载并重新安装应用程序,则无法帮助您。
一个简单的技巧是在外部存储器中保存它,直到android 10为止(根据谷歌,在android 11上将不再可能),如果第一次使用应用程序时查找此类文件,如果存在则读取UUID,否则生成新的UUID并保存文件。
这种策略的问题是,您需要WRITE_EXTERNAL_STORAGE权限。
如果这不是问题,只需...
new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + ".my_hidden_folder").mkdir();

任何保存在此文件夹中的文件将对用户隐藏,不会在卸载您的应用程序时被删除。
我个人使用
Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

这并不会造成伤害,只是谷歌不喜欢你这样做。


1

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

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

您可以从此链接了解更多Android 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();
}

0

相当长一段时间以前,我需要为每个设备创建一个持久的唯一标识符,但遇到了同样的问题。以下是我找到的解决方案:

  1. IMEI:最糟糕的解决方案:没有SIM卡的Android设备(如许多平板电脑)被排除在外,您需要请求“拨打电话”权限才能获取它,但没有人愿意授予此权限。

  2. 设备序列号:很好的解决方案,具有唯一值;但在API级别26中已弃用,并且新方法需要在Android 10中获得权限。

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

一些半唯一的解决方案包括:

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

Build.TIME:自设备ROM生产以来的毫秒数。

提示:混合硬件属性不起作用,因为它们可能相似(工厂生产大量的模型),为了实现唯一的ID,您可能需要权限。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接