安卓设备ID混乱

44

如果我拨打 * # * # 8 2 5 5 # * # * , 我会得到以 android-35c2acdd... 开头的 Android 设备 ID。

source source

如果我使用 Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID),结果以 a96b4b27... 开头。

如果我使用 ((TelephonyManager) Context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(),结果以 3538330... 开头。

这些 ID 有什么区别?如何获取

* # * # 8 2 5 5 # * # * 拨号?

5个回答

83

IMEI

IMEI是电话模块的 'MAC' - 电话连接GSM/GPRS/HSPDA等时所使用的唯一标识符。GSM网络使用它来路由电话和数据从手机通过GSM网络直到进入互联网的网关(即IP网络)。

电话模块是处理电话网络的芯片或电路板,可以是GSM或CMDA,并且通常具有可拆卸的SIM卡槽。一些手机具有多个电话模块(活动双卡或多卡手机)。每个电话模块都有自己的IMEI。

制造商在制造过程中为每个手机(严格来说是电话模块)分配一个唯一的IMEI。但是如果您有正确的软件,通常可以重新编写该号码。这通常是在手机被盗后执行的,以给手机一个新的身份并绕过被盗手机阻止系统。

可以使用TelephonyManager.getDeviceId() API编程方式获取IMEI。

CDMA手机拥有ESN或MEID,其长度和格式不同,尽管它们使用相同的API检索。

没有电话模块的Android设备 - 例如许多平板电脑和电视设备 - 没有IMEI。正如Schlangi所评论的那样,一些没有电话模块的设备伪造了IMEI,因此IMEI的存在并不总是保证设备具有电话模块。

ANDROID_ID

ANDROID_ID是手机上的另一个唯一编号 - 当操作系统第一次启动时会自动生成此编号(通过这种方式可以使制造商更轻松,从生产线中删除一个步骤)。

ANDROID_ID可以(而且确实)更改,例如:

它主要由开发人员使用(例如使用 adb 来识别和连接设备)

ANDROID_ID 可以用于识别 Android 设备,但需要注意上述限制,实际上意味着它可以在设备寿命的大部分时间内唯一标识设备,但不能保证其可靠性。

还要注意,在 Froyo 中存在一个错误,许多设备会赋予自己相同的 ANDROID_ID。这是bug

其他标识符

还有许多其他可以用来识别设备的东西:

  • WiFi模块的MAC地址:WifiManager.getConnectionInfo() -> WifiInfo.getMacAddress()。这通常可以通过软件更改,但通常在设备寿命内是恒定的。如果WiFi模块关闭,则无法读取。
  • 蓝牙模块的MAC地址:BluetoothAdaptor.getAddress()。与WiFi MAC类似,这通常可以通过软件更改,并且当您需要时可能会关闭。
  • 用户的电话号码。如果用户从电信公司请求新号码或更换SIM卡,则此号码可能会更改。它是从TelephonyManager.getLine1Number()获取的。仅适用于安装有当前SIM卡和已付费电信服务的Android手机设备。
  • SIM卡包含其自己的识别号码(IMSI)。这是从TelephonyManager.getSubscriberId() API获取的。显然,SIM卡可能在任何特定时间不存在,并且在更换SIM卡时会更改-用户可以升级/更换其SIM卡而保持相同的号码,因此无法说这是一对一的到特定的电话或用户。
  • 与IMSI相关的是MSISDN。这作为订阅的标识符(您与移动提供商签订的特定电话号码的合同),因此为设备提供其电话号码。 MSISDN可能与多个SIM卡和因此多个电话相关联。它随所有上面读取SIM的警告而来。可以使用TelephonyManager.getSimSerialNumber()检索此信息。感谢Schlangi进行更正和补充。
  • Gingerbread及更高版本具有android.os.Build.SERIAL,许多制造商设置了该值(但不是全部。讨厌)。

其他注意事项

您需要特定的权限才能访问每个API,因此如果您尝试访问所有API,则您的应用程序在Google Play商店中的权限看起来相当宽容。

我认为此链接还解释了所有其他可用选项https://android-developers.googleblog.com/2011/03/identifying-app-installations.html


1
尽管您的说法是正确的,没有电话模块的设备确实没有IMEI,但有些制造商会给他们的设备伪造IMEI。其中一个例子是Odys的低成本设备Loox plus - 因此,如果您尝试以特殊方式处理这些设备,请不要指望在调用TelephonyManager.getDeviceId()时获得null或空字符串! - Schlangi
1
我在你的解释中发现了一个小错误:IMSI是由TelephonyManager.getSubscriberId()报告的,SIM卡的序列号是另一回事:可以制作多个副本使用相同的IMSI但不同的序列号。结果是SIM卡,可以在不同的手机上使用相同的电话号码(例如智能手机和车载电话),但每次只能使用一个。这是移动网络能够处理每个电话号码可以同时使用多个IMSI之前的常见用例。 - Schlangi
@Schlangi:感谢您的评论-我已更新我的答案以澄清所有这些细节。如果我搞砸了什么,请告诉我 :) - Andrew Alcock
这在安卓10上可行吗?https://developer.android.com/about/versions/10/privacy/changes#non-resettable-device-ids - Amin Pinjari

8

在网上找到:

private static final Uri URI = Uri.parse("content://com.google.android.gsf.gservices");
private static final String ID_KEY = "android_id";

String getAndroidId(Context ctx) {
    String[] params = { ID_KEY };
    Cursor c = ctx.getContentResolver()
            .query(URI, null, null, params, null);

    if (!c.moveToFirst() || c.getColumnCount() < 2)
        return null;

    try {
        return Long.toHexString(Long.parseLong(c.getString(1)));
    } catch (NumberFormatException e) {
        return null;
    }
}

添加权限:

<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>

然而,我怀疑这不是一个已记录的ID,如果GTalk得到更新,它可能会无法使用。
来源:http://blog.codepainters.com/2012/01/17/how-to-obtain-gtalk-android-id/ 也值得一看:http://www.toxicbakery.com/android-development/getting-google-auth-sub-tokens-in-your-android-applications/

这是手机上特定于Google服务的ID。当您在设备上设置第一个(主要)Google帐户时,它会生成。它只是一个长(64位)数字,并用于所有Google服务,包括Android市场。除非您正在尝试编写访问Google服务的应用程序,否则通常不需要它(参见上面的第二个链接)。 - Nikolay Elenkov

5

有一些方法可以在Android手机上获得唯一标识符。

  1. Android ID 这是一个64位的十六进制字符串,由设备在第一次启动时生成。 通常情况下,除非进行工厂重置,否则不会改变。

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

Android ID被认为不可靠,因为它有时可能为空。 文档说明它“可能在工厂重置时更改”。 此字符串也可以在已获取root权限的手机上更改。

   String m_szAndroidID = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

Returns: 9774d56d682e549c . No special permissions required.

2. WLAN MAC地址字符串是另一个可以用作设备ID的唯一标识符。在阅读之前,您需要确保您的项目具有android.permission.ACCESS_WIFI_STATE权限,否则WLAN MAC地址将显示为null。

 WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
 String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();
Returns: 00:11:22:33:44:55 (not a real address since this is a custom ROM , as you can see the MAC address can easily be faked).
WLAN doesn't have to be on, to read this value.

3. 如果你的项目拥有android.permission.BLUETOOTH权限,则可以读取在Android设备上具有蓝牙功能的BT MAC地址字符串。

    BluetoothAdapter m_BluetoothAdapter = null; // Local Bluetooth adapter
    m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
   String m_szBTMAC = m_BluetoothAdapter.getAddress();

返回结果:43:25:78:50:93:38。BT不必打开即可读取。

4. 仅适用于带有电话使用的Android设备的IMEI:

 TelephonyManager TelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
 String szImei = TelephonyMgr.getDeviceId(); // Requires READ_PHONE_STATE

在AndroidManifest.xml文件中添加一个权限android.permission.READ_PHONE_STATE,用户在安装您的软件时将会被通知。IMEI是手机的唯一标识符,形式如下:359881030314356(除非您使用的是一个具有无效IMEI(如0000000000000)的预生产设备)。更多信息请参考此链接。


3

IMEI

标准化机构要求公共网络的移动设备必须通过IMEI号码进行唯一识别

设置IMEI是制造商的责任。实际上,开发人员有时会看到像000000...或123456...这样的IMEI。有时相同IMEI的手机会进入生产,这当然是一个需要修复的错误....

ANDROID_ID

64位数字(以十六进制字符串形式)在设备首次启动时随机生成,并应该在设备使用期间保持不变。(如果在设备上执行出厂重置,则值可能会更改。)

看起来Android不信任制造商并提供了一个替代的唯一ID。

编辑:

这是我在一个非手机安卓设备上获得的(而不是IMEI):

$ adb shell dumpsys iphonesubinfo
Phone Subscriber Info:
  Phone Type = GSM
  Device ID = null

我怎样才能获取 *#*#8255#*#* 拨号的结果? - Gergely Fehérvári

1

我认为上面提供的所有信息足以理解代码。

但我认为您仍然“无法看到##8255##拨号的结果”(如果我在理解上有误,请原谅)

我猜这背后的原因是Android中针对USSD代码进行的最新错误修复之一。 (您可以阅读更多相关信息并检查您的设备是否在列表中。这些信息遍布整个网络)

最后,如果您只想直接获取Android ID,我建议您使用此应用程序-

https://play.google.com/store/apps/details?id=com.redphx.deviceid&hl=en


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