设备恢复出厂设置时Android Device ID变更,需始终唯一的设备标识
Android 刷机/恢复出厂后获取永久唯一标识的可行方案
当设备执行恢复出厂设置或刷机后,Android Device ID这类软件级标识会被重置,想要获取不受操作影响的唯一标识,只能依赖硬件级别的固有信息,以下是几种可行方案:
1. IMEI/MEID(仅适用于带蜂窝网络的设备)
IMEI是手机基带芯片固化的国际移动设备识别码,MEID是CDMA设备的对应标识,这类信息不受刷机、恢复出厂操作影响。
代码实现
import android.content.Context; import android.telephony.TelephonyManager; public String getIMEI(Context context) { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { return telephonyManager.getImei(); } else { // 适配Android 8.0以下版本 return telephonyManager.getDeviceId(); } }
注意事项
- 仅支持手机等带蜂窝模块的设备,WiFi版平板、智能手表等设备无法获取。
- Android 10及以上版本需要申请
READ_PHONE_STATE权限,且用户有权拒绝授权;授权后也可能被用户随时撤销。
2. 设备序列号(Serial Number)
设备出厂时写入硬件存储的序列号,绝大多数设备的序列号不会因刷机、恢复出厂改变。
代码实现
import android.os.Build; public String getSerialNumber() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return Build.getSerial(); } else { // 适配Android 8.0以下版本 return Build.SERIAL; } }
注意事项
- 部分小众设备可能存在序列号为空的情况。
- Android 8.0及以上版本需要
READ_PHONE_STATE权限,低版本无需权限,但部分厂商可能限制读取。
3. WiFi MAC地址(仅root/系统级应用可用)
WiFi模块的硬件MAC地址是固化的,但Android 6.0+系统默认对普通应用返回随机MAC,只有root权限或系统签名的应用才能读取真实的硬件MAC。
代码实现(仅root/系统应用)
import java.io.BufferedReader; import java.io.InputStreamReader; public String getRealMacAddress() { try { // 读取WiFi硬件地址文件 Process process = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String mac = reader.readLine().trim(); reader.close(); return mac; } catch (Exception e) { e.printStackTrace(); return null; } }
4. 多标识组合哈希方案
如果单一硬件标识不可靠(比如平板没有IMEI),可以将多个可用的硬件标识(如序列号、主板ID等)拼接后做哈希运算,生成唯一字符串。
代码实现
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public String generateUniqueId(String... identifiers) { StringBuilder sb = new StringBuilder(); // 拼接所有非空的硬件标识 for (String id : identifiers) { if (id != null && !id.isEmpty()) { sb.append(id); } } try { // 使用SHA-256生成哈希值 MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] hashBytes = md.digest(sb.toString().getBytes()); StringBuilder hexStr = new StringBuilder(); for (byte b : hashBytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) hexStr.append('0'); hexStr.append(hex); } return hexStr.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } }
使用示例
// 传入序列号和IMEI(如果有)生成唯一标识 String uniqueId = generateUniqueId(getSerialNumber(), getIMEI(context));
关键注意点
- 所有硬件标识的读取都可能受系统权限限制,Android 10+对隐私权限管控更严格,普通应用无法保证100%获取到所需信息。
- 绝对不要依赖Android ID、广告ID这类软件级标识,它们会在恢复出厂或刷机后被重置。
- 没有任何方案能覆盖所有设备,不同厂商的硬件设计和系统限制可能导致部分标识无法读取,建议同时兼容多种方案。
内容的提问来源于stack exchange,提问作者Gprakash
相关产品推荐
相关产品推荐

