稳定获取Android设备唯一码(UUID)的解决方案

最近做的一个项目中需要用到Android设备唯一码(UUID)来标识一台设备,

Android中设备唯一码有很多,如:MAC地址、IMEI号(DeviceId)、IMSI号、ANDROID_ID、序列号(SerialNumber)等,

但并不是所有设备上都能稳定获取到这些值。

 

最后项目中采用的是MAC地址。

先总结一些搜索得知的各种值的缺点,再说说最后采用MAC地址的解决方案吧。

 

1.MAC地址:

获取MAC地址的方法有两种:

(1). 通过Linux命令查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public String getMacAddress() {
     String macAddress = null ;
     String str = "" ;
     try {
         //linux下查询网卡mac地址的命令
         Process pp = Runtime.getRuntime().exec( "cat /sys/class/net/wlan0/address" );
         InputStreamReader ir = new InputStreamReader(pp.getInputStream());
         LineNumberReader input = new LineNumberReader(ir);
 
         for (; null != str;) {
             str = input.readLine();
             if (str != null ) {
                 macAddress = str.trim(); // 去空格
                 break ;
             }
         }
     } catch (IOException ex) {
         ex.printStackTrace();
     }
     return macAddress;
}

缺点:

在当前没打开WiFi的情况下获取得到的MAC地址值为空,即使在执行这段代码前是有打开过WiFi,而执行这段代码时WiFi状态是关闭的,也不能获取到MAC地址。

 

(2). 通过Android官方的WifiManager类获取

1
2
3
4
5
6
7
8
9
10
11
public String getMacAddress() {
 
     String macAddress = null ;
         
     WifiManager wifiManager =
         (WifiManager)MyApplication.getContext().getSystemService(Context.WIFI_SERVICE);
     WifiInfo info = ( null == wifiManager ? null : wifiManager.getConnectionInfo());
         
     macAddress = info.getMacAddress();
     return macAddress;
}

需要加入权限

1
< uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />

缺点:

这种方法虽然能在当前Wifi状态为关闭的情况下获取到MAC地址,但前提是在手机开机后要打开过一次Wifi,如果在某次开机后没打开过Wifi就调用这段代码,获取地址也是为空。

网上给出的解释是:WiFi的Mac address是一个被动资讯。一般在开机后,不会主动上报到系统裡。要待WiFi硬件启动后,才会把有关Mac address资料记载入系统去。

 

2.IMEI号(DeviceId)、IMSI号:

1
2
3
TelephonyManager mTelephonyMgr = (TelephonyManager) getSystemServic(Context.TELEPHONY_SERVICE);
String imsi = mTelephonyMgr.getSubscriberId();  //获取IMSI号
String imei = mTelephonyMgr.getDeviceId();  //获取IMEI号

需要加入权限

1
< uses-permission android:name = "android.permission.READ_PHONE_STATE" />

缺点:

IMEI号(国际移动设备身份码)、IMSI号(国际移动设备识别码)这两个是有电话功能的移动设备才具有,也就是说某些没有电话功能的平板是获取不到IMEI和IMSI号的。且在某些设备上getDeviceId()返回垃圾数据。

 

3.ANDROID_ID:

ANDROID_ID 是设备首次启动时由系统随机生成的一串64位的十六进制数字。

1
String ANDROID_ID = Settings.System.getString(getContentResolver(), Settings.System.ANDROID_ID);

缺点:

①.设备刷机wipe数据或恢复出厂设置时ANDROID_ID值会被重置。

②.现在网上已有修改设备ANDROID_ID值的APP应用。

③.某些厂商定制的系统可能会导致不同的设备产生相同的ANDROID_ID。

④.某些厂商定制的系统可能导致设备返回ANDROID_ID值为空。

⑤.CDMA设备,ANDROID_ID和DeviceId返回的值相同

 

4.序列号SerialNumber:

从Android 2.3开始,通过android.os.Build.SERIAL方法可获取到一个序列号。没有电话功能的设备也都需要上给出此唯一的序列号。

1
String SerialNumber = android.os.Build.SERIAL;

缺点:

在某些设备上此方法会返回垃圾数据。

 

解决方案:

一种比较折衷的办法,在获取MAC地址之前先判断当前WiFi状态,若开启了Wifi,则直接获取MAC地址,若没开启Wifi,则用代码开启Wifi,然后马上关闭,再获取MAC地址。

目前此方法测试成功,无论在哪种状态下都能正确取得设备的MAC地址(包括开机后未启动过Wifi的状态下),且在未开启Wifi的状态下,用代码开启Wifi并马上关闭,过程极短,不会影响到用户操作。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public String getMacAddress() {
 
     String macAddress = null ;
     WifiManager wifiManager =
         (WifiManager)MyApplication.getContext().getSystemService(Context.WIFI_SERVICE);
     WifiInfo info = ( null == wifiManager ? null : wifiManager.getConnectionInfo());
         
     if (!wifiManager.isWifiEnabled())
     {
         //必须先打开,才能获取到MAC地址
         wifiManager.setWifiEnabled( true );
         wifiManager.setWifiEnabled( false );
     }
     if ( null != info) {
         macAddress = info.getMacAddress();
     }
     return macAddress;
}

需要加入如下权限

1
2
3
< uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" > </ uses-permission >
< uses-permission android:name = "android.permission.CHANGE_WIFI_STATE" > </ uses-permission >
< uses-permission android:name = "android.permission.WAKE_LOCK" > </ uses-permission >

 

来自:http://www.goteny.com/develop/android/201412/452.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VCHH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值