android 獲得設備唯一標識碼(總有一款適合你)

白嫖黨可直接下滑到最後 (手動滑稽) 繞開那些不太完美的辦法

場景

最近在做一個OA考勤項目,裏面有個需求是一個賬號只允許綁定一臺設備, 這就需要將設備唯一標識碼與賬號綁定在一起,咋一聽 這還不So Easy啊,直接獲取deviceID 不就好了。。。

問題

private String getSerial() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        return Build.getSerial();
    } else {
        return Build.SERIAL;
    }
}

咋一操作也挺好。 可到了大面積的羣體用戶測試環節發現了幾個問題。

  1. 需要獲取手機READ_PHONE_STATE權限,這個權限涉及的信息還挺多。我們爲了設備id有點大材小用
  2. 在努比亞和一加手機上有返回null 和 000000 ,應該是廠商在這方面做了特別的處理來保護用戶隱私
  3. 在Android10 就已經完全獲取不到,返回unknown
  4. 如果是雙卡,其中一張卡是電信的,手機是小米的,那麼你更換卡槽的位置,deviceId會從IMIE1 變爲MEID。華爲、榮耀等機型未發現。(當然也有解決辦法獲取 getDeviceId(0)的方式)

在Android 10以下版本雖然可以獲取到IMEI碼,但是需要在應用獲取到了READ_PHONE_STATE權限,並且我們仍然沒法保證所有的設備都能正常返回


簡言之就是如果你的手機需要考慮Android9以上的設備,你就沒辦法通過獲取系統提供的API完全的獲取到設備唯一標識碼,根據Android文檔唯一標識符最佳做法你也許可以這樣…


唯一標識符最佳做法

呃… 這個特殊運營商許可 和這個 READ_PRIVILEGED_PHONE_STATE 好像都不是我們一般的安卓應用能獲取的到的。

想要能Android9以上又能不受到刷機,格式化的影響。 就只能 使用移動安全聯盟(MSA)提出的補充設備標識

是由移動安全聯盟提出的,包含以下三個標識:

名稱 說明
OAID 匿名設備標識符,最長64爲,所有應用都獲取到同一個ID,但是用戶可關閉、可重置
AAID 應用匿名設備標識符,最長64爲,每個應用獲取到各自的ID
VAID 開發者匿名設備標識符,最長64爲,同一開發者不同應用獲取到的一致

缺點就是:並不是所有的品牌商都兼容了, 而且需要導入他們對應的包 。 這部分可參考 Android 10獲取設備標識方案探究 這篇文章


樓主的做法

androidId + 序列號+ 硬件信息(品牌+型號)

特點: 如果格式化或者刷機,這個設備ID會更改(這個也是合理的)。

完善:可以在第一次生成後放入到內部存儲和外部存儲,下次進入先從內部存儲獲取,如果沒有在去外部存儲比較(App卸載,內部存儲就沒了)。 如果在沒有就生成一個

public class SystemUtils {
    /**
     *   ANDROID_ID(恢復出廠+刷機會變) + 序列號(android 10會unknown/android 9需要設備權限)+品牌    +機型
     * @return
     */
    @SuppressLint("MissingPermission")
    public static String getUniqueIdentificationCode(FragmentActivity context){
        String androidId =  Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        String uniqueCode ;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            /** 需要權限 且僅適用9.0。 10.0後又不能獲取了*/
            uniqueCode = androidId + Build.getSerial()+Build.BRAND+ Build.MODEL;
        }else{
            uniqueCode = androidId + Build.SERIAL+Build.BRAND+ Build.MODEL;
        }
      return toMD5(uniqueCode);
    }

    /**
     * MD5加密 格式一致
     */
    private static String toMD5(String text){                                                                                  
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        byte[] digest = messageDigest.digest(text.getBytes());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < digest.length; i++) {
            int digestInt = digest[i] & 0xff;
            //將10進制轉化爲較短的16進制
            String hexString = Integer.toHexString(digestInt);
            if (hexString.length() < 2) {
                sb.append(0);
            }
            sb.append(hexString);
        }
        return sb.toString().substring(8,24);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章