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

时间:2016-10-27 11:25:01

标签: android telephonymanager android-settings android-identifiers

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

我使用了以下代码来获取唯一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。

有什么解决方案吗?它有害还是其他什么?

5 个答案:

答案 0 :(得分:1)

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();
}

答案 1 :(得分:0)

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

但是如果你想要,你可以通过添加@SuppressLint(“HardwareIds”)来禁用警告,这将解决这个问题。

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

答案 2 :(得分:0)

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

    UUID.randomUUID().toString()

您可以将其保存在SharedPreferences中,轻松完成工作。不需要权限

问题在于,如果用户卸载并重新安装该应用程序,它将无法为您提供帮助。

一个可能要到android 10才做的简单技巧(根据google在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);

这不是有害的,只是Google不喜欢您这么做

答案 3 :(得分:0)

我正在使用设备Build.SERIAL来获取设备的唯一ID

String serial ="";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    ActivityCompat.requestPermissions(MainActivity.mainContext, new String[]{Manifest.permission.READ_PHONE_STATE}, RequestCode);
    if (ActivityCompat.checkSelfPermission(MainActivity.mainContext, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
        // Application Needs permission.READ_PHONE_STATE permission
    } else {
        serial = Build.getSerial();
    }
} else {            
        serial = Build.SERIAL;       
}

我已将此解决方案用于已发布的应用,并且Android 10或旧版Android都能完美运行。

答案 4 :(得分:0)

很早以前,我需要为每个设备拥有一个永久的唯一ID,并且遇到了相同的问题。 这是我找到的解决方案:

  1. IMEI:最糟糕的解决方案:没有SIM卡的Android设备(例如大量平板电脑)将被排除在外,您需要获得“拨打电话”权限才能获得,这是没人愿意授予的。

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

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

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

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

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

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

>

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