获取Android设备唯一标识

很多情况下,需要将APP和设备进行绑定,以保证用户不会无限制的注册或发送请求。然而,Android设备并没有绝对的唯一标识。
Android提供了多种方法来获取所谓的唯一标识。常用的有六种。

(1)Android ID

确实有一个叫做Android ID的东西,但通常被认为不可信,因为它有时会为NULL。而且,在ROOT后,该值可以被修改。

String sAndroidID= Secure.getString(getContentResolver(), Secure.ANDROID_ID);

(2)WLAN MAC

首先,需要说明的是,获取该值需要添加权限。

android.permission.ACCESS_WIFI_STATE

其次,需要指出的是,获取该值无须打开WIFI。
最后,需要强调的是,该值不是真实地址,可以被伪造。

由于android系统对获取方法进行了升级。
android 6.0之前的版本,获取方法如下:

WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE); 
String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();

若无法获取该值,或值为02:00:00:00:00:00,则说明系统为Android 6.0或以上,需要使用以下方法获取。

public static String getMacAddr() {
    try {
        List all = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface nif : all) {
            if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

            byte[] macBytes = nif.getHardwareAddress();
            if (macBytes == null) {
                return "";
            }

            StringBuilder res1 = new StringBuilder();
            for (byte b : macBytes) {
                res1.append(String.format("%02X:",b));
            }

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
    }
    return "02:00:00:00:00:00";
}

注:该方法也无须打开WIFI。

(3)Blue Tooth MAC

与WLAN MAC类似,获取该值需要添加权限。

android.permission.BLUETOOTH 

同样,获取方法也以Android 6.0作为分界点。
Android 6.0以下,使用如下方法获取

BluetoothAdapter m_BluetoothAdapter = null; // Local Bluetooth adapter      
m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();      
String m_szBTMAC = m_BluetoothAdapter.getAddress();

Android 6.0及以上,获取方法可参见Stackoverflow,该方法需要到入mirror包。(为取个唯一标识,至于吗?这里不再详述)

同样, 蓝牙没有必要打开,也能读取该值。

注:此前,某些帖子说添加ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION 权限后,可以获取蓝牙或WIFI的MAC,也是瞎扯。仅添加两项权限,不能获取MAC值。若不添加两项权限,也可以获取MAC值。因此,该两项不是必要条件。

(4)IMEI

IMEI,即International Mobile Equipment Identity,是国际移动设备身份码的缩写,国际移动装备辨识码,是由15位数字组成的”电子串号”。
获取该值,需要添加权限

android.permission.READ_PHONE_STATE

获取方法如下:

TelephonyManager TelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); 
String szImei = TelephonyMgr.getDeviceId(); 

该值与SIM卡有关,但不是所有Android设备都有SIM卡。
且需要考虑双卡双待情况。

(5)Pseudo Device ID

方法2至方法4,都尝试以某种硬件的信息作为Android的唯一标识,但无法保证该值得唯一性和有效性。很自然可以想到,使用多硬件信息组合作为唯一标识。例如取出ROM版本、CPU型号、以及其他硬件信息进行组合。获取这些信息,需要用到Build类。大多数的Build成员都是字符串形式的,但网上流传比较广的使用方法,是使用各成员的长度,进行字符串组合。

Build.BOARD.length()%10 + 
Build.BRAND.length()%10 + 
Build.CPU_ABI.length()%10 + 
Build.DEVICE.length()%10 + 
Build.DISPLAY.length()%10 + 
Build.HOST.length()%10 + 
Build.ID.length()%10 + 
Build.MANUFACTURER.length()%10 + 
Build.MODEL.length()%10 + 
Build.PRODUCT.length()%10 + 
Build.TAGS.length()%10 + 
Build.TYPE.length()%10 + 
Build.USER.length()%10 ; 

当然,我们也可以只使用其中某几个成员,获取其字符串值进行组合,再辅助于某种运算(SHA, MD5,HASH等)来生成自定义的唯一标识。

(6)APP UUID

还有一种方法,使用了Android UUID类,实现了APP与设备的绑定。
在通过APP第一次获取设备唯一标识时,创建文件,并使用UUID类向文件中写入一个随机字符串,作为唯一标识。下次获取时,若文件存在,则直接读取随机字符串。当卸载APP时,删除该文件。因此,一次安装APP,对应一个唯一标识。

public synchronized static String getUUID(Context context, String fileName) {
        if (sID == null) {
            File UUIDFile= new File(context.getFilesDir(), fileName);
            try {
                if (!UUIDFile.exists())
                    writeInstallationFile(UUIDFile);
                sID = readInstallationFile(UUIDFile);
            } catch (Exception e){
                throw new RuntimeException(e);
            }
        }
        return sID;
    }
    private static String readInstallationFile(File file) throws IOException {
        RandomAccessFile f = new RandomAccessFile(file, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }
    private static void writeInstallationFile(File file) throws IOException {
        FileOutputStream out = new FileOutputStream(file);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }

APP UUID值例如:

7a2c6658-1d61-42f5-99b1-c7d309c60d50

综上,设备的唯一标识,不是绝对的。我们可以选择一种或多种进行组合,最大可能的实现其唯一性。

你可能感兴趣的:(android,Tips,Android,Tips)