【问题标题】:How can I get the UUID of my Android phone in an application?如何在应用程序中获取我的 Android 手机的 UUID?
【发布时间】:2011-07-02 14:07:05
【问题描述】:

我正在寻求帮助以获取我的 Android 手机的 UUID。我已经在网上搜索并找到了一种可能的解决方案,但它在模拟器中不起作用。

代码如下:

Class<?> c;
try {
    c = Class.forName("android.os.SystemProperties");
    Method get = c.getMethod("get", String.class);
    serial = (String) get.invoke(c, "ro.serialno");
    Log.d("ANDROID UUID",serial);
} catch (Exception e) {
    e.printStackTrace();
}

有人知道它为什么不起作用,或者有更好的解决方案吗?

【问题讨论】:

  • @Mudassir Thaks。我看了看,所以那里有很多关于你的问题的答案,但这是乐观的。我还找到了一个基于主机名、MAC 地址、操作系统名称和版本生成唯一 UUID 的解决方案。但是如何获取内置的 UUID。
  • 没有内置的 UUID。按照 Mudassir 的建议,您在首次启动时生成了 Android ID,或者您有 IMEI,这是制造商提供的 GSM 设备的唯一 ID。
  • 谢谢你 Zelimir,这消除了我的怀疑。所以使用 UUID 生成算法我会生成一个。所以这就足够了吗?
  • 我注意到 ro.serialnoandroid.os.Build.SERIAL 在带有 Gingerbread 的 Nexus-One 上是相同的。

标签: android uuid


【解决方案1】:

正如 Dave Webb 所提到的,Android Developer Blog has an article 涵盖了这一点。他们首选的解决方案是跟踪应用安装而不是设备,这适用于大多数用例。这篇博文将向您展示完成这项工作所需的代码,我建议您查看一下。

但是,如果您需要设备标识符而不是应用程序安装标识符,该博客文章会继续讨论解决方案。如果您需要这样做,我与 Google 的某个人进行了交谈,以获得对一些项目的额外说明。以下是我在上述博文中未提及的有关设备标识符的发现:

  • ANDROID_ID 是首选设备标识符。 ANDROID_ID 在 Android =2.3 的版本上非常可靠。只有2.2有帖子中提到的问题。
  • 几家制造商的几款设备受到 2.2 中的 ANDROID_ID 错误的影响。
  • 据我所知,所有受影响的设备都有the same ANDROID_ID,即9774d56d682e549c。顺便说一句,这也是模拟器报告的相同设备 ID。
  • Google 认为 OEM 已为他们的许多或大部分设备修复了该问题,但我能够验证,至少在 2011 年 4 月开始,仍然很容易找到 ANDROID_ID 损坏的设备。
  • 当一个设备有多个用户(available on certain devices running Android 4.2 or higher) 时,每个用户都显示为一个完全独立的设备,因此 ANDROID_ID 值对于每个用户都是唯一的。

根据 Google 的建议,我实现了一个类,该类将为每个设备生成一个唯一的 UUID,在适当的情况下使用 ANDROID_ID 作为种子,必要时使用 TelephonyManager.getDeviceId(),如果失败,则使用随机生成的唯一 UUID 在应用重新启动(但不是应用重新安装)时保持不变。

请注意,对于必须回退设备 ID 的设备,唯一 ID 在出厂重置后仍然存在。这是需要注意的。如果您需要确保恢复出厂设置会重置您的唯一 ID,您可能需要考虑直接回退到随机 UUID 而不是设备 ID。

同样,此代码用于设备 ID,而不是应用安装 ID。在大多数情况下,应用程序安装 ID 可能就是您要查找的内容。但如果您确实需要设备 ID,那么下面的代码可能适合您。

import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

public class DeviceUuidFactory {
    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";

    protected static UUID uuid;



    public DeviceUuidFactory(Context context) {

        if( uuid ==null ) {
            synchronized (DeviceUuidFactory.class) {
                if( uuid == null) {
                    final SharedPreferences prefs = context.getSharedPreferences( PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null );

                    if (id != null) {
                        // Use the ids previously computed and stored in the prefs file
                        uuid = UUID.fromString(id);

                    } else {

                        final String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);

                        // Use the Android ID unless it's broken, in which case fallback on deviceId,
                        // unless it's not available, then fallback on a random number which we store
                        // to a prefs file
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                            } else {
                                final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();
                                uuid = deviceId!=null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) : UUID.randomUUID();
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }

                        // Write the value out to the prefs file
                        prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();

                    }

                }
            }
        }

    }


    /**
     * Returns a unique UUID for the current android device.  As with all UUIDs, this unique ID is "very highly likely"
     * to be unique across all Android devices.  Much more so than ANDROID_ID is.
     *
     * The UUID is generated by using ANDROID_ID as the base key if appropriate, falling back on
     * TelephonyManager.getDeviceID() if ANDROID_ID is known to be incorrect, and finally falling back
     * on a random UUID that's persisted to SharedPreferences if getDeviceID() does not return a
     * usable value.
     *
     * In some rare circumstances, this ID may change.  In particular, if the device is factory reset a new device ID
     * may be generated.  In addition, if a user upgrades their phone from certain buggy implementations of Android 2.2
     * to a newer, non-buggy version of Android, the device ID may change.  Or, if a user uninstalls your app on
     * a device that has neither a proper Android ID nor a Device ID, this ID may change on reinstallation.
     *
     * Note that if the code falls back on using TelephonyManager.getDeviceId(), the resulting ID will NOT
     * change after a factory reset.  Something to be aware of.
     *
     * Works around a bug in Android 2.2 for many devices when using ANDROID_ID directly.
     *
     * @see http://code.google.com/p/android/issues/detail?id=10603
     *
     * @return a UUID that may be used to uniquely identify your device for most purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }
}

【讨论】:

  • 1.你为什么使用 Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);我们什么时候可以直接从 Secure.ANDROID_ID 访问常量? 2. 我们不能用 UUID.fromString(ANDROID_ID) 代替 getBytes("utf8") 吗?
  • 您为什么选择不将此代码也发布到 GitHub 或类似的地方,以便共享和维护?
  • @AWrightIV 答案应该是独立的;链接到 Github 与我们的目标相反
  • Android Studio 3.1.3 创建一个警告,告诉不要使用 getString()。帖子仍然很有帮助,但我想有点过时了?
【解决方案2】:

这对我有用:

TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String uuid = tManager.getDeviceId();

编辑:

您还需要在您的清单中设置android.permission.READ_PHONE_STATE。由于 Android M,您需要在运行时请求此权限。

看到这个答案:https://stackoverflow.com/a/38782876/1339179

【讨论】:

  • 因为你在模拟器上测试。
  • 是的,Zelimir 我在设备上对其进行了测试,它运行良好,非常感谢您的帮助。
  • 请注意,它仅适用于手机。没有电话的设备(例如平板电脑)不会有这个
  • 但是这个可以在平板电脑上使用developer.android.com/reference/android/provider/…
  • 它不是 uuid 而是 IMEI,所以称它为 uuid 就像为每个认为它是 uuid 的人制造错误
【解决方案3】:

不要从 TelephonyManager 获取 IMEI,而是使用 ANDROID_ID。

Settings.Secure.ANDROID_ID

这适用于每个 android 设备,无论是否有电话。

【讨论】:

    【解决方案4】:
     String id = UUID.randomUUID().toString();
    

    Android Developer blog article for using UUID class to get uuid

    【讨论】:

    • 这是正确的答案。不需要清单权限。
    • 问题是获取设备 UUID 而不是随机的
    【解决方案5】:
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    

    【讨论】:

      【解决方案6】:

      从 API 26 开始,不推荐使用 getDeviceId()。如果您需要获取设备的 IMEI,请使用以下命令:

       String deviceId = "";
          if (Build.VERSION.SDK_INT >= 26) {
              deviceId = getSystemService(TelephonyManager.class).getImei();
          }else{
              deviceId = getSystemService(TelephonyManager.class).getDeviceId();
          }
      

      【讨论】:

        【解决方案7】:

        添加

          <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
        

        方法

        String getUUID(){
            TelephonyManager teleManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
            String tmSerial = teleManager.getSimSerialNumber();
            String tmDeviceId = teleManager.getDeviceId();
            String androidId = android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
            if (tmSerial  == null) tmSerial   = "1";
            if (tmDeviceId== null) tmDeviceId = "1";
            if (androidId == null) androidId  = "1";
            UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDeviceId.hashCode() << 32) | tmSerial.hashCode());
            String uniqueId = deviceUuid.toString();
            return uniqueId;
        }
        

        【讨论】:

        • 工作得很好,很好的后备。由于我是 Android 编程的 n00b,所以直到我在页面上请求 Manifest.permission.READ_PHONE_STATE 之前它对我不起作用
        • 感谢您的建议,这是一个补充。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-17
        • 1970-01-01
        相关资源
        最近更新 更多