在我們的APP開(kāi)發(fā)中,通常需要獲取到設(shè)備的唯一標(biāo)識(shí)。在Android6.0之前磨镶,有很多方法我們可以方便獲取到硬件的唯一標(biāo)識(shí)邪蛔,但是在Android6.0之后急黎,Android系統(tǒng)大幅限制了我們獲取設(shè)備的硬件信息。
Android6.0之前的方法(已過(guò)時(shí))
DEVICE_ID
通getSystemService(Context.TELEPHONY_SERVICE).getDeviceId()獲取侧到,但是6.0之后必須申請(qǐng)READ_PHONE_STATE勃教,并且獲取到的這個(gè)值在不同的廠商和設(shè)備中并不可靠。MAC地址
這個(gè)是無(wú)線網(wǎng)卡的MAC地址匠抗,這個(gè)需要ACCESS_WIFI_STATE權(quán)限故源,并且很多情況下并獲取不到這個(gè)值,也并不是十分可靠汞贸。ANDROID_ID
這個(gè)值是當(dāng)一個(gè)新的設(shè)備第一次啟動(dòng)時(shí)绳军,或者恢復(fù)出廠設(shè)置時(shí),系統(tǒng)會(huì)生成一個(gè)64位的數(shù)字矢腻,這個(gè)值目前(Android4.0之后)已經(jīng)非趁偶荩可靠,但是仍有個(gè)別廠商的定制系統(tǒng)的BUG多柑,導(dǎo)致這個(gè)值返回null奶是。
獲取設(shè)備唯一標(biāo)識(shí)的正確姿勢(shì)
由于ANDROID_ID的值相對(duì)穩(wěn)定和可靠,并且不需要申請(qǐng)權(quán)限,所以我們獲取設(shè)備的唯一標(biāo)識(shí)應(yīng)該使用這個(gè)值聂沙,同時(shí)我們應(yīng)該考慮到一些極端情況和安全問(wèn)題秆麸。
- 獲取ANDROID_ID
public static String getAndroidID() {
String id = Settings.Secure.getString(
Utils.getApp().getContentResolver(),
Settings.Secure.ANDROID_ID
);
return id == null ? "" : id;
}
- 構(gòu)造UUID,防止直接暴露ANDROID_ID
private static String getDeviceUUid()
{
String androidId = DeviceUtils.getAndroidID();
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)androidId.hashCode() << 32));
return deviceUuid.toString();
}
- 考慮極端情況逐纬,我們自己生成一個(gè)應(yīng)用級(jí)別的UUID
這種情況我們需要將生成的UUID保存到SharedPreference中蛔屹,只要應(yīng)用不被卸載或者清除數(shù)據(jù),這個(gè)值就不會(huì)變豁生。
private static String getAppUUid() {
String uuid = SPUtils.getInstance().getString(PREF_KEY_UUID);
if (TextUtils.isEmpty(uuid)) {
uuid = UUID.randomUUID().toString();
//這里需要保存到SharedPreference中
...
}
return uuid;
}
- 將上面的獲取方法封裝到一個(gè)方法中
public static String getUUID() {
String uuid = getDeviceUUid();
if (TextUtils.isEmpty(uuid)) {
uuid = getAppUUid();
}
return uuid;
}
總結(jié)
這些獲取UUID方法非常簡(jiǎn)單兔毒,并且在應(yīng)用的開(kāi)發(fā)中可以滿足99%的需求,不需要?jiǎng)討B(tài)申請(qǐng)權(quán)限甸箱,也非秤可靠,但是在使用時(shí)需要清楚其生成過(guò)程芍殖,以便應(yīng)用到安全性要求非常高的場(chǎng)景中豪嗽。
如有更多疑問(wèn),請(qǐng)參考我的其它Android相關(guān)博客:我的博客地址