Android设备唯一标识在开发中常被用于识别设备、进行用户行为分析、实现个性化推送等功能。出于隐私和安全考虑,一些标识码(如IMEI和MAC地址)的获取和使用可能受到一定的限制。在开发过程中,需要遵守相关的隐私政策和法规,确保用户数据的安全和合规性。
Android设备的唯一标识主要包括以下几种:
- 「IMEI(国际移动设备识别码)」:IMEI是International Mobile Equipment Identity的缩写,即通常所说的手机序列号、手机“串号”。它是由15位数字组成的“电子串号”,相当于移动电话的身份证,用于在移动电话网络中识别每一部独立的手机等移动通信设备。IMEI码由GSM(全球移动通信协会)统一分配,授权BABT(英国通信认证管理委员会)审受。
- 「MEID」:MEID是移动设备识别码的另一种形式,主要用于CDMA制式的手机。
- 「MAC地址」:MAC地址是媒体访问控制地址,也称为物理地址或硬件地址,用于在网络中唯一标识一个网络设备。
- 「ANDROID_ID」:ANDROID_ID是Android系统为设备分配的一个唯一ID,主要用于应用程序内部识别设备。
- 「UUID(通用唯一识别码)」:UUID是一个软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分。其目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。
- 「OAID」:OAID(Open Anonymous Device Identifier,开放匿名设备标识符)是移动广告行业为了遵循用户隐私保护政策而推出的一种设备标识符。
IMEI
IMEI(国际移动设备识别码)是一个重要的设备标识符,用于唯一地识别每一部移动电话。IMEI码由15位数字组成,每部移动电话的IMEI码都是独一无二的。识别码可以帮助运营商和制造商追踪设备的来源和状态,以及在需要时进行远程控制。
在Android应用中获取IMEI:
- 「添加权限」:在应用的AndroidManifest.xml文件中添加读取电话状态的权限。
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
- 「获取TelephonyManager」:获取一个TelephonyManager实例。
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- 「获取IMEI」:使用TelephonyManager的getDeviceId()方法可以获取设备的IMEI。
String imei = telephonyManager.getDeviceId();
注意点:
- 「隐私政策」:IMEI是设备的敏感信息,在获取和使用IMEI之前,须确保应用遵守了相关的隐私政策和法规。需要在应用的隐私政策中明确告知用户将收集和使用IMEI,并且获得用户的明确同意。
- 「权限变更」:从Android 6.0(API 级别 23)开始,运行时权限模型引入后,需要在运行时请求READ_PHONE_STATE权限。
- 「可用性」:在某些情况下,例如模拟器或者没有SIM卡的设备,getDeviceId()可能会返回null或者一个非标准的值。在获取IMEI后,应该检查它是否为null或有效。
- 「兼容性」:对于Android 10(API 级别 29)及以上版本,由于隐私保护的增强,非系统应用可能无法访问IMEI。在这种情况下可能需要寻找其他方式来标识设备或用户。
- 「Google Play 政策」:确保应用遵守Google Play的政策,特别是在处理用户数据方面。不当的数据收集和使用可能导致应用被从Google Play中移除。
MEID
MEID是移动设备识别码的一种形式,主要用于CDMA制式的手机或通讯平板。类似于每部CDMA设备的“身份证号”,通过这个识别码,网络端可以对设备进行跟踪和监管。在移动通信网络中,MEID是识别移动设备的重要依据,有助于确保设备的合法性和在网络中的正常使用。MEID也可以用于设备追踪、保修验证等目的。
在Android应用中获取MEID:
- 「添加权限」:在AndroidManifest.xml文件中添加读取电话状态的权限。
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
- 「获取TelephonyManager」:获取一个TelephonyManager实例。
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- 「获取MEID」:使用TelephonyManager的getMeid()方法可以获取设备的MEID。
//8.0以后,区分IMEI和MEID
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d(TAG, "getImei:" + manager.getImei());
Log.d(TAG, "getMeid:" + manager.getMeid());
} else {
//8.0之前:不区分IMEI和MEID,在安卓8.0废弃
Log.d(TAG, "getDeviceId:" + manager.getDeviceId());
}
MAC地址
MAC地址是指设备的物理地址,也叫做硬件地址。MAC地址是网络设备在网络中的唯一标识,由一串英文加数字的字符串组成,具有全球唯一性。每个网络设备,包括手机、电脑、路由器等,都有一个唯一的MAC地址。这个地址不会随网络或位置的更改而变化,因此能够准确地标识特定设备。
在Android设备上,可以通过特定的路径查看MAC地址。一般可以在“设置”菜单中找到“关于手机”或“关于设备”选项,选择“状态消息”或“网络状态”等子菜单找到“WLAN MAC地址”或类似的选项。
Android MAC地址是设备在网络中的唯一标识符,对于设备通信和网络管理都起着关键作用,但也应注意其潜在的安全风险。
在Android设备上,有多种方法可以获取MAC地址。以下是两种常见的方法:
方法一:通过WifiManager获取
- 通过getSystemService(Context.WIFI_SERVICE)方法获取到WifiManager的实例。
- 使用getConnectionInfo()方法获取到连接信息。
- 调用getMacAddress()方法获取MAC地址。
方法二:通过NetworkInterface获取
- 获取设备上的网络接口列表。通过调用NetworkInterface.getNetworkInterfaces()方法实现,方法会返回一个枚举类型的网络接口列表。
- 遍历这个接口列表,找到以太网接口。
- 在找到以太网接口后,通过该接口的getHardwareAddress()方法获取MAC地址。
从Android 6.0(API级别23)开始,运行时权限引入后,需要在运行时请求访问网络状态的权限。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Android_id
ANDROID_ID是Android系统提供的一个用于标识设备的唯一ID。是一个64位的十六进制字符串,由16个字符组成,是设备特定的标识符,可以用于唯一地标识一个Android设备。
在Android 8.0(API 26级)和更高版本的平台上,64位数字(表示为十六进制字符串),对于应用程序签名密钥、用户和设备的每个组合都是唯一的。ANDROID_ID的值由签名密钥和用户限定范围。如果在设备上执行出厂重置或APK签名密钥发生更改,则该值可能会更改。
在低于Android 8.0(API 26级)的平台版本中,用户首次设置设备时随机生成的64位数字(表示为十六进制字符串),在用户设备的使用寿命内应保持不变。在具有多个用户的设备上,每个用户都显示为一个完全独立的设备,因此ANDROID_ID值对每个用户都是唯一的。
ANDROID_ID的生成是基于设备的硬件信息和操作系统的版本号等,在同一台设备上是固定的,但是在不同的设备上是不同的。ANDROID_ID是在设备首次启动时生成的。存储在设备的/data/data/com.android.providers.settings/databases/settings.db数据库中的secure表中。在设备首次启动时,系统会检查secure表是否存在一个名为android_id的条目,如果不存在,则会生成一个唯一的ANDROID_ID,并插入到secure表中。如果设备被恢复出厂设置,则会重新生成一个新的ANDROID_ID。
虽然ANDROID_ID是唯一的,但不是100%可靠的,因为可以被某些应用程序修改或篡改。如果重置设备,ANDROID_ID也会被重置。刷机或者更换了ROM,ANDROID_ID也会被重置。
//在 Android 8.0(API 级别 26)及更高版本中,SSAID(AndroidID) 提供了一个在由同一开发者签名密钥签名的应用之间通用的标识符。
//当设备恢复出厂设置,或者Root过的话,OTA升级系统,值会被改变
public static void getAndroidId(Context context){
String androidId = Settings.Secure.getString(context.getApplicationContext().getContentResolver(),Settings.Secure.ANDROID_ID);
Log.d(TAG, "androidId:" + androidId);
}
UUID
UUID(Universally Unique Identifier,全局唯一标识符)是一种软件建构的标准,亦为开放软件基金会(OSF)组织在分布式计算环境(DCE)领域的一部分。UUID是一个128位的字符串,通常以32个十六进制数字表示,按照8-4-4-4-12的36个字符格式分成五段,形式为8-4-4-4-12的32个字符,例如:550e8400-e29b-41d4-a716-446655440000。
UUID的主要目的是提供唯一性,减少冲突的可能性,并且不依赖于中央注册机构来分配标识符。由于UUID的生成算法使用了一些随机的元素(如当前的时间戳和机器标识符),因此它可以在不同的系统和应用程序中生成几乎不重复的标识符。
//在大多数非广告用例中,可用于跟踪已注销用户的偏好设置,这是建议的解决方案
public static void getUUID(){
String uniqueID = UUID.randomUUID().toString();
Log.d(TAG, "UUID:" + uniqueID);
}
OAID
OAID(Open Anonymous Device Identifier,开放匿名设备标识符)是移动广告行业为了遵循用户隐私保护政策而推出的一种设备标识符。它的主要目的是在保护用户隐私的前提下,为广告主和开发者提供一种替代IMEI、Android ID等传统设备标识符的方式,以便进行广告跟踪、效果衡量和个性化推送等操作。
OAID具有以下特点:
- 「匿名性」:OAID是匿名的,不会直接关联到用户的个人信息,从而保护了用户的隐私。
- 「可重置性」:用户可以在设备的设置中选择重置OAID,广告主和开发者就无法继续追踪该设备。
- 「合规性」:由于OAID遵循了用户隐私保护政策,使用OAID进行广告跟踪和数据分析更符合法规要求。
在Android设备上,OAID通常由广告服务提供商或设备制造商提供。开发者需要集成相应的SDK(软件开发工具包)来获取OAID。开发者可以将其用于广告跟踪、推送通知等目的。
具体使用可以查看各厂商的说明文档手册:
小米OAID: https://dev.mi.com/distribute/doc/details?pId=1634
OPPO OAID: https://open.oppomobile.com/new/developmentDoc/info?id=12344
华为OAID: https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/oaid-0000001050783198
考虑到隐私和安全的问题,如果应用不需要IMEI,MEID来进行关键功能,最好避免收集和使用。可以考虑使用其他方法来标识设备或用户,比如使用ANDROID_ID,OAID或者生成一个UUID来在应用中标识设备。