Android 设备唯一标识生成方式

时间:2022-09-23 11:40:35

Android设备唯一标识生成方式

为什么很多安卓应用都要获取IMEI?

很多应用都会要求获取IMEI,尤其神奇的是,我禁用了天猫客户端的权限,弹出来一行英文,大概是什么内容获取不到,无法登录,又试了一次,登录成功,发现权限管理里权限竟然被打开了。

像天猫(支付宝)/微信这样的登陆时校验一下设备串号是有意义的这是用来确保是由你的设备在登陆。

IMEI一般作手机的唯一标识,用于服务端日志统计,数据分析。

但是有些厂商的设备,IMEI并不是总能够获取到,解决的办法就是我们手动生成一个ID值,后面再详细讲解。

 

一、IMEI获取

imei是设备的一个编号值,获取比较方便,不过有些设备的设备编号获取不到,这种方式已经没有多少人会采用。下面就讲讲怎么获取imei编号。

1、首先要获取到设备的imei编号,必须得开启权限,在AndroidManifest.xml文件中添加入下字段:

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

2、获取imei值

private TelephonyManager manager;
manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
imei = manager.getDeviceId();
tv.setText(imei);

 

二、UUID生成

UUID生成的原理,先获取设备的标识信息,如果能够获取到就使用该获取到的值,否则就生成一个随机数,然后通过缓存和文件的方式保存这个值。

1、生成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) {
                    uuid = UUID.fromString(id);
                } else {
                    if (recoverDeviceUuidFromSD() != null) {
                        uuid = UUID.fromString(recoverDeviceUuidFromSD());
                    } else {
                        final String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                                try {
                                    saveDeviceUuidToSD(EncryptUtils.encryptDES(uuid.toString(), KEY));
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            } else {
                                final String deviceId = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
                                uuid = deviceId != null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) : UUID.randomUUID();
                                try {
                                    saveDeviceUuidToSD(EncryptUtils.encryptDES(uuid.toString(), KEY));
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString()).commit();
                }
            }
        }
    }
}

存缓存和读缓存的方式,上面的源码已经写出了处理方式,就不多讲了。

2、将UUID保存到SD卡的文件中的方法

private static void saveDeviceUuidToSD(String uuid) {
    String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    File targetFile = new File(dirPath, DEVICE_UUID_FILE_NAME);
    if (targetFile != null) {
        if (targetFile.exists()) {

        } else {
            OutputStreamWriter osw;
            try {
                osw = new OutputStreamWriter(new FileOutputStream(targetFile), "utf-8");
                try {
                    osw.write(uuid);
                    osw.flush();
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

}

 

3、将UUID从文件中读取出来的方法

private static String recoverDeviceUuidFromSD() {
    try {
        String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        File dir = new File(dirPath);
        File uuidFile = new File(dir, DEVICE_UUID_FILE_NAME);
        if (!dir.exists() || !uuidFile.exists()) {
            return null;
        }
        FileReader fileReader = new FileReader(uuidFile);
        StringBuilder sb = new StringBuilder();
        char[] buffer = new char[100];
        int readCount;
        while ((readCount = fileReader.read(buffer)) > 0) {
            sb.append(buffer, 0, readCount);
        }
        //通过UUID.fromString来检查uuid的格式正确性
       
UUID uuid = UUID.fromString(EncryptUtils.decryptDES(sb.toString(), KEY));
        return uuid.toString();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

4、获取UUID

public static UUID getUuid() {
    return uuid;
}

说明几点:

1、读写文件需要开启SDCard的读写权限,在AndroidManifest.xml文件中添加入下字段:

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

2、调用方法

 private DeviceUuidFactory uuidFactory;
 uuidFactory = new DeviceUuidFactory(this);
 tv1.setText(uuidFactory.getUuid() + "");

3、因为是以文件的形式保存的uuid值,容易被人修改,所以我采用了以下两种方式:

1)将文件作为隐藏文件保存,例如:

   DEVICE_UUID_FILE_NAME = ".dev_id.txt"
         2)我采用了DES对生成的uuid值进行了加密存储,这样在一定程度上能够确保内容不会被修改,绝对不能够被修改我个人觉得是不现实的。
 
具体的实现请参照事例demo中的源码。

源码下载地址:http://download.csdn.net/detail/zhimingshangyan/9479722