`

Android 手机上获取物理唯一标识码

阅读更多

 

  1. 所有添加有谷歌账户的设备可以返回一个 ANDROID_ID
  2. 所有的CDMA设备对于 ANDROID_ID 和 TelephonyManager.getDeviceId() 返回相同的值(只要在设置时添加了谷歌账户)

 

唯一标识码这东西在网络应用中非常有用,例如检测是否重复注册之类的。

import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID);

 

我们在项目过程中或多或少会使用到设备的唯一识别码,我们希望能够得到一个稳定、可靠的设备唯一识别码。今天我们将介绍几种方式。

       1. DEVICE_ID

 

假设我们确实需要用到真实设备的标识,可能就需要用到DEVICE_ID。在以前,我们的Android设备是手机,这个DEVICE_ID可以同通过getSystemService(Context.TELEPHONY_SERVICE).getDeviceId()获取,它根据不同的手机设备返回IMEI,MEID或者ESN码,但它在使用的过程中会遇到很多问题:

  • 非手机设备: 如果只带有Wifi的设备或者音乐播放器没有通话的硬件功能的话就没有这个DEVICE_ID
  • 权限: 采用此种方法,需要在AndroidManifest.xml中加入一个许可:android.permission.READ_PHONE_STATE,并且用户应当允许安装此应用。作为手机来讲,IMEI是唯一的,它应该类似于 359881030314356(除非你有一个没有量产的手机(水货)它可能有无效的IMEI,如:0000000000000)。,但如果我们只为了获取它,没有用到其他的通话功能,那这个权限有点大才小用
  • bug:在少数的一些手机设备上,该实现有漏洞,会返回垃圾,如:zeros或者asterisks的产品

 

        2. MAC ADDRESS

 

我们也可以通过手机的Wifi或者蓝牙设备获取MAC ADDRESS作为DEVICE ID,但是并不建议这么做,因为并不是所有的设备都有Wifi,并且,如果Wifi没有打开,那硬件设备无法返回MAC ADDRESS.

The WLAN MAC Address string, 是另一个唯一ID。但是你需要为你的工程加入android.permission.ACCESS_WIFI_STATE 权限,否则这个地址会为null。

 WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE); String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();

Returns: 00:11:22:33:44:55 (这不是一个真实的地址。而且这个地址能轻易地被伪造。).WLan不必打开,就可读取些值。

The BT MAC Address string, 只在有蓝牙的设备上运行。并且要加入android.permission.BLUETOOTH 权限.

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

Returns: 43:25:78:50:93:38 . 蓝牙没有必要打开,也能读取。

 

        3. Serial Number

装有SIM卡的设备可以通过getSystemService(Context.TELEPHONY_SERVIEC).getSimSerialNumber();获取到

sim serial number。 注意对CDMA设备,返回的是一个空值。

在Android 2.3可以通过android.os.Build.SERIAL获取,非手机设备可以通过该接口获取。

        4. ANDROID_ID

ANDROID_ID是设备第一次启动时产生和存储的64bit的一个数,当设备被wipe后该数重置

ANDROID_ID似乎是获取Device ID的一个好选择,但它也有缺陷:

 

  • 它在Android <=2.1 or Android >=2.3的版本是可靠、稳定的,但在2.2的版本并不是100%可靠的
  • 在主流厂商生产的设备上,有一个很经常的bug,就是每个设备都会产生相同的ANDROID_ID:9774d56d682e549c
  • String m_szAndroidID = Secure.getString(getContentResolver(), Secure.ANDROID_ID)

 

        5. Installtion ID : UUID

以上四种方式都有或多或少存在的一定的局限性或者bug,在这里,有另外一种方式解决,就是使用UUID,该方法无需访问设备的资源,也跟设备类型无关。

这种方式是通过在程序安装后第一次运行后生成一个ID实现的,但该方式跟设备唯一标识不一样,它会因为不同的应用程序而产生不同的ID,而不是设备唯一ID。因此经常用来标识在某个应用中的唯一ID(即Installtion ID),或者跟踪应用的安装数量。很幸运的,Google Developer Blog提供了这样的一个框架:

public class Installation {
    private static String sID = null;
    private static final String INSTALLATION = "INSTALLATION";

    public synchronized static String id(Context context) {
        if (sID == null) {  
            File installation = new File(context.getFilesDir(), INSTALLATION);
            try {
                if (!installation.exists())
                    writeInstallationFile(installation);
                sID = readInstallationFile(installation);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return sID;
    }

    private static String readInstallationFile(File installation) throws IOException {
        RandomAccessFile f = new RandomAccessFile(installation, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }

    private static void writeInstallationFile(File installation) throws IOException {
        FileOutputStream out = new FileOutputStream(installation);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }
}

6 Pseudo-Unique ID, 这个在任何Android手机中都有效
有一些特殊的情况,一些如平板电脑的设置没有通话功能,或者你不愿加入READ_PHONE_STATE许可。而你仍然想获得唯一序列号之类的东西。这时你可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出来的ID不是唯一的(因为如果两个手机应用了同样的硬件以及Rom 镜像)。但应当明白的是,出现类似情况的可能性基本可以忽略。要实现这一点,你可以使用Build类:

String m_szDevIDShort = "35" + //we make this look like a valid IMEI 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 digits  

大多数的Build成员都是字符串形式的,我们只取他们的长度信息。我们取到13个数字,并在前面加上“35”。这样这个ID看起来就和15位IMEI一样了。

   总结

综合以上所述,为了实现在设备上更通用的获取设备唯一标识,我们可以实现这样的一个类,为每个设备产生唯一的UUID,以ANDROID_ID为基础,在获取失败时以TelephonyManager.getDeviceId()为备选方法,如果再失败,使用UUID的生成策略

 

 

 

分享到:
评论
4 楼 zi413293813 2015-08-17  
第六点我觉得同样的厂商生产的同款设备,很有可能是一样的,个人觉得最不靠谱的就是第六点。按照长度来,有可能完全不一样的手机,算出来也是一样的,还不如把这些信息用MD5之类的工具运算一下,得出一个字符串
3 楼 zi413293813 2015-08-17  
第二点说错了,wifi mac不管打不打开,都能拿到;蓝牙mac有些机器,如果蓝牙没打开,就拿不到,比如三星S5660 2.3.4系统版本.
2 楼 892848153 2014-06-22  
第六点我也没试过,但我感觉,用这么多得Builder里面的信息算出来的ID,应该是唯一的可能性很高。有兴趣可以拿两部一样的手机刷同一个ROOM,然后运行下看一样不。
1 楼 JAVA一小菜 2014-06-20  
关于第六点,“因为如果两个手机应用了同样的硬件以及Rom 镜像”。这个为什么说可能性基本没有?这个不是应该是概率最高的吗?

相关推荐

    Android手机唯一标识

    在Android操作系统中,寻找一个设备的唯一标识是一个常见的需求,特别是在开发...综上所述,"Android手机唯一标识"涉及多个标识的获取、使用和组合,需要在尊重用户隐私的同时,找到一个尽可能稳定且独特的设备标识。

    Android-一个获取Android设备唯一id的工具类

    1. **IMEI(国际移动设备识别码)**:这是GSM和UMTS网络中手机的唯一标识,可以通过`TelephonyManager`获取。IMEI对于具有物理SIM卡槽的设备是有效的,但在没有SIM卡或使用Wi-Fi连接的设备上可能不可用。 2. **...

    安卓登录注册相关-唯一标识一台Android设备手机平板手表电视.rar

    1. **IMEI(国际移动设备识别码)**:这是手机硬件的全球唯一标识,通常用于区分物理设备。每个带有蜂窝数据功能的Android设备都有一个IMEI。不过,IMEI在非手机设备(如平板、手表、电视)上可能不可用。 2. **...

    Android生成唯一标识符UUID(完全替代IMEI)

    在早期,IMEI(国际移动设备识别码)是广泛使用的设备唯一标识,但随着隐私保护政策的加强,IMEI的获取和使用受到了限制。在这种背景下,使用UUID作为IMEI的替代方案变得越来越常见。本文将深入探讨如何在Android中...

    android 获取手机上面的IMSI序列号

    在Android平台上,开发人员有时需要访问设备的特定标识符,以实现特定功能,如设备唯一标识、定位服务或网络状态检测。本文将详细介绍如何在Android应用中获取IMSI(国际移动用户识别码)、IMEI(国际移动设备识别码...

    Android_获取手机IP和MAC地址

    而MAC地址(Media Access Control Address)则是物理网络接口控制器的唯一标识,通常用于局域网内的设备识别。 在Android应用中获取IP地址,我们主要依赖于网络连接的状态。以下是一段简单的代码示例,展示了如何...

    获取 Windows Mobile 设备的唯一标识

    在开发针对Windows Mobile设备的应用程序时,...需要注意的是,随着移动平台的发展,如Windows Phone和现代的Android、iOS,获取设备唯一标识的方法可能会有所变化,因此开发者应始终关注最新的平台文档和技术更新。

    Android应用源码获取手机信息.zip源码资源下载

    2. **IMEI(国际移动设备识别码)**:IMEI是手机的唯一标识,通常用于区分不同的手机。在Android中,可以通过`TelephonyManager`的`getDeviceId()`方法获取,但需要注意,这需要`READ_PHONE_STATE`权限。 3. **MAC...

    android 获取系统信息

    MAC地址是设备在网络中的唯一物理标识。在Android中,可以通过`WifiManager`类来获取MAC地址。首先需要请求`ACCESS_WIFI_STATE`权限,然后通过`Context.getSystemService(Context.WIFI_SERVICE)`获取`WifiManager`...

    Android 移动端获取设备MAC Demo

    在Android平台上,开发移动应用时有时需要获取设备的物理MAC(Media Access Control)地址,这在设备定位、网络连接管理或者其他需要唯一标识设备的场景中非常有用。MAC地址是网络接口控制器(NIC)的硬件地址,它在...

    获取手机上的各种信息

    5. **手机MAC地址**:物理设备的唯一标识,但出于隐私考虑,Android 6.0及以后版本不再允许直接访问,需要依赖网络接口。在iOS中,自iOS 7起,Apple也限制了直接获取MAC地址,通常会返回一个随机值。 6. **IMEI...

    Android 获取手机imei值和mac值.zip

    在Android平台上,IMEI(International Mobile Equipment Identity)和MAC(Media Access Control)地址是两种用于唯一标识设备的重要标识。IMEI是手机的国际移动设备识别码,通常用于区分不同的手机设备,而MAC地址...

    通过NDK获得UUID

    标题"通过NDK获得UUID"和描述涉及到利用Native Development Kit (NDK) 在Android系统底层获取UUID,以及通过Java层获取Android的唯一标识码。NDK允许开发者用C/C++编写部分应用,从而提高性能,特别是对于计算密集型...

    Android获取MAC

    MAC地址是一个物理网络接口控制器的唯一标识符,用于在局域网(LAN)中区分不同的设备。以下是Android获取MAC地址的三种常见方法: ### 1. 使用`WifiManager` `WifiManager`是Android提供的一个系统服务,主要用于...

    android设备信息获取源码

    IMSI(International Mobile Subscriber Identity)是国际移动用户识别码,是运营商分配给SIM卡的唯一标识。获取IMSI同样需要`TelephonyManager`: ```java if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {...

    jni获取Android设备MAC Address最完美解决方案

    MAC地址(Media Access Control Address)是网络设备的物理地址,每个网络接口控制器都有一个唯一的MAC地址,用于标识网络上的设备。在Android系统中,由于隐私和安全原因,直接通过Java API获取MAC地址的方法已被...

    安卓手机mac物理地址修改工具

    在现代网络通信中,MAC(Media Access Control)地址是设备在网络中的唯一标识,通常由六组两进制数字组成,用于区分同一网络中的不同设备。在Android操作系统中,出于某些特殊需求,例如测试、隐私保护或者模拟不同...

    android 获取mac地址源码

    在Android平台上,获取设备的MAC地址是一个常见的需求,特别是在实现设备唯一标识或者网络通信时。MAC(Media Access Control)地址是设备在网络层的物理地址,它是一个48位的二进制数,通常以冒号或破折号分隔的12...

    如何使用Java代码获取Android移动终端Mac地址.zip

    在Android平台上,Mac地址是设备网络接口控制器的物理地址,通常用于唯一标识网络硬件。由于隐私和安全原因,从Android 6.0(API级别23)开始,系统对此进行了限制,不再允许应用直接获取Mac地址。不过,仍有一些...

    安卓获取手机系统内核wifi的mac地址等信息

    4. **Wi-Fi MAC地址**:在安卓设备上,每个无线网络接口都有一个物理地址,即MAC地址,用于在网络中唯一识别设备。Wi-Fi MAC地址可通过编程方式获取,一般使用`WifiManager`类的`getMacAddress()`方法。然而,从...

Global site tag (gtag.js) - Google Analytics