Android设备获取唯一标识符
2016-05-09 17:34
435 查看
概述
有时需要对用户设备进行标识,所以希望能够得到一个稳定可靠并且唯一的识别码。虽然Android系统中提供了这样设备识别码,但是由于Android系统版本、厂商定制系统中的Bug等限制,稳定性和唯一性并不理想。唯一标识码这东西在网络应用中非常有用,例如检测是否重复注册之类的。下面就来介绍几种标识码:
1.DEVICE_ID;
2.MAC ADDRESS;
3.Sim Serial Number;
4.Serial Number;
5.ANDROID_ID;
6.Installtion ID : UUID;
7.DEVICE_ID:UUID;
DEVICE_ID
概念: 是区别移动设备的标志,储存在移动设备中,可用于监控被窃或无效的移动设备。关键代码:
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String IMEI = tm.getDeviceId();
优点:
1.根据不同的手机设备返回IMEI,MEID或者ESN码,唯一性良好 。
不足:
1.非手机:如平板电脑,像这样设备没有通话的硬件功能,系统中也就没有TELEPHONY_SERVICE,自然也就无法获得DEVICE_ID;
2.权限问题:获取DEVICE_ID需要READ_PHONE_STATE权限;
3.厂商定制系统中的Bug:少数手机设备上,由于该实现有漏洞,会返回垃圾,如:00000000或者****
MAC ADDRESS
概念:可以使用手机Wifi或蓝牙的MAC地址作为设备标识。Wifi Mac关键代码:
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); String wlan_mac = wm.getConnectionInfo().getMacAddress();
蓝牙 Mac关键代码:
String bt_mac = BluetoothAdapter.getDefaultAdapter().getAddress();
不足:
1.如果设备没有支持WIFI的硬件,就返回null;
2.如果设备没有支持蓝牙的硬件,就返回null。
Sim Serial Number
概念:SIM卡的序列号。关键代码:
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String SimSerialNumber = tm.getSimSerialNumber();
不足:
1.没有装Sim卡时,返回null;
2.对于CDMA设备,返回null。
Serial Number
概念:Android系统2.3版本以上可以获取硬件Serial Number。关键代码:
String sn = android.os.Build.SERIAL;
优点:非手机设备也可以通过该接口获取ID。
ANDROID_ID
概念:当设备首次启动时,系统会随机生成一个64位的数字,并把这个数字以16进制字符串的形式保存下来。关键代码:
String android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
不足:
1.它在Android <=2.1 or Android >=2.3的版本是可靠、稳定的,但在2.2的版本并不是100%可靠的;
2.在主流厂商生产的设备上,有一个很经常的bug,就是每个设备都会产生相同的ANDROID_ID。
Installation ID : UUID
概念:该标识符无需访问设备的资源,也跟设备类型无关。这种标识符是通过在程序安装后第一次运行后生成一个ID实现的,但该标识跟设备唯一标识不一样,它会因为不同的应用程序而产生不同的ID,而不是设备唯一ID。关键代码:
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(); } }
不足:
1.当卸载应用后重新安装,返回值与之前的值不同。
DEVICE_ID:UUID
概念:为了实现在设备上更通用的获取设备唯一标识,我们可以实现这样的一个类,为每个设备产生唯一的UUID,以ANDROID_ID为基础,在获取失败时以TelephonyManager.getDeviceId()为备选方法,如果再失败,使用UUID的生成策略。关键代码:
public class DeviceUuidFactory { protected static final String PREFS_FILE = "device_id.xml"; protected static final String PREFS_DEVICE_ID = "device_id"; protected static UUID uuid; public DeviceUuidFactory(Context context) { if (uuid == null) { synchronized (DeviceUuidFactory.class) { if (uuid == null) { final SharedPreferences prefs = context.getSharedPreferences(PREFS_FILE, 0); final String id = prefs.getString(PREFS_DEVICE_ID, null); if (id != null) { // Use the ids previously computed and stored in the prefs file uuid = UUID.fromString(id); } else { final String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); try { if (!"9774d56d682e549c".equals(androidId)) { uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8")); } else { final String deviceId = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); uuid = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) : UUID.randomUUID(); } } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } // Write the value out to the prefs file prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString()).commit(); } } } } } public UUID getDeviceUuid() { return uuid; } }
相关文章推荐
- Android ——对AsyncTask的理解和注意事项
- 读书笔记(15) Android性能优化
- android中的线程池的使用
- Android动画效果(一) 任意两点间的抛物线动画
- Android 关机流程 从kernel到framework
- Android之SurfaceView
- 兔子-android studio出现ADB not responding. If you'd like to retry, then please manually kill "adb.exe" a
- Android-系统服务
- Android-EditText相关
- Android查看数据库工具sqlitemanager
- android 蓝牙通信编程
- 猴子都能看懂的Android Menu总结
- Android开发自定义控件实现一个饼状图
- 安卓加载视频缩略图,展示于ListView中,完美实现
- androidStudio 自定义控件时在XML使用xmlns自定义命名空间时报错?
- android watchDog 机制
- android两种自定义属性的方法
- Android中View绘制流程
- java.lang.NoSuchMethodError: android.view.View.setBackground
- Android中跨进程通信方式之使用Bundle