Android設備獲取唯一標識符

概述

有時需要對用戶設備進行標識,所以希望能夠得到一個穩定可靠並且唯一的識別碼。雖然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;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章