Android 获取设备唯一ID

时间:2023-01-08 17:44:49

只能在安卓手机上,需要支持Sim芯片,需要在AndroidManifest.xml中加入一个许可:android.permission.READ_PHONE_STATE,并且用户应当允许安装此应用。作为手机来讲,IMEI是唯一的,它应该类似于 359881030314356(除非你有一个没有量产的手机(水货)它可能有无效的IMEI,如:0000000000000)。注意:在双卡双待的手机上imei不是唯一,因为有2个还有getDeviceId在电信卡上得到的是meid,和imei完全不一样。
获取办法:
String serialNum = android.os.Build.SERIAL;
装有SIM卡的设备获取办法:getSystemService(Context.TELEPHONY_SERVIEC).getSimSerialNumber();

 private String getImei(){
TelephonyManager TelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
String szImei = TelephonyMgr.getDeviceId();
return szImei;
}

android ID常被认为不可信,因为它有时为null。开发文档中说明了:这个ID会改变如果进行了出厂设置。并且,如果某个Andorid手机被Root过的话,这个ID也可以被任意改变。

   private String getAndroidId(){
String m_szAndroidID = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
return m_szAndroidID;
}

获取wlan芯片的mac地址,是另一个唯一ID。但是你需要为你的工程加入android.permission.ACCESS_WIFI_STATE 权限,否则这个地址会为null。
不需要打开wifi

 private String getWlanId(){
WifiManager wm = (WifiManager)getSystemService(getApplicationContext().WIFI_SERVICE);
String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();
return m_szWLANMAC;
}

获取蓝牙芯片的mac地址,只在有蓝牙的设备上运行。并且要加入android.permission.BLUETOOTH 权限,不需要打开蓝牙

  private String getBlueTooth(){
BluetoothAdapter m_BluetoothAdapter = null; // Local Bluetooth adapter
m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String m_szBTMAC = m_BluetoothAdapter.getAddress();
return m_szBTMAC;
}

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

  private String getPseudo(){
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
return m_szDevIDShort;
}
android.os.Build.BOARD:获取设备基板名称
android.os.Build.BOOTLOADER:获取设备引导程序版本号
android.os.Build.BRAND:获取设备品牌
android.os.Build.CPU_ABI:获取设备指令集名称(CPU的类型)
android.os.Build.CPU_ABI2:获取第二个指令集名称
android.os.Build.DEVICE:获取设备驱动名称
android.os.Build.DISPLAY:获取设备显示的版本包(在系统设置中显示为版本号)和ID一样
android.os.Build.FINGERPRINT:设备的唯一标识。由设备的多个信息拼接合成。
android.os.Build.HARDWARE:设备硬件名称,一般和基板名称一样(BOARD)
android.os.Build.HOST:设备主机地址
android.os.Build.ID:设备版本号。
android.os.Build.MODEL :获取手机的型号 设备名称。
android.os.Build.MANUFACTURER:获取设备制造商
android:os.Build.PRODUCT:整个产品的名称
android:os.Build.RADIO:无线电固件版本号,通常是不可用的 显示unknown
android.os.Build.TAGS:设备标签。如release-keys 或测试的 test-keys
android.os.Build.TIME:时间
android.os.Build.TYPE:设备版本类型 主要为"user""eng".
android.os.Build.USER:设备用户名 基本上都为android-build
android.os.Build.VERSION.RELEASE:获取系统版本字符串。如4.1.22.22.3
android.os.Build.VERSION.CODENAME:设备当前的系统开发代号,一般使用REL代替
android.os.Build.VERSION.INCREMENTAL:系统源代码控制值,一个数字或者git hash值
android.os.Build.VERSION.SDK:系统的API级别 一般使用下面大的SDK_INT 来查看
android.os.Build.VERSION.SDK_INT:系统的API级别 数字表示

设备唯一标识码还是以utdid做标识,但是在Android6.0+系统上,外存储权限越来越难获取和越来越不可靠的情况下,除考虑加入LocalSocket和Broadcast等机制做多应用间的utdid同步(问题也很明显)外,必须依赖网络,构建设备ID库来提升设备标识的可靠性。
因此需要考虑在服务器上建立utdid与各设备数据间的对应关系,通过做大规模的适配和数据上报,来解决问题。通过可获得手机参数做服务器请求,服务器的utdid与各设备数据间的对应关系表来寻找最匹配utdid值。
可以考虑的数据关系体系是以Wifi Mac地址、设备序列号、ANDROID_ID为主要基准,配合android.os.Build中手机基本信息为参考(用手机root相关信息采集做修正),DEVICE_ID(用READ_PHONE_STATE权限做修正),常用ip地址等。如果可以的话,还可以参考手机号码、业务登录账号等。目前只是一些初步想法,可行性还有待实际数据验证,方案还在探索阶段。