Android獲取的IMEI只有14位問題解決


此文章已收入Android偶遇雜症合集(持續更新)

1、遇到的問題

在手機設置里的信息上IMEI有15位的數字,但通過代碼獲得卻只有14位,少了最后一位數字。手機重新開機,代碼獲得了正確的15位數字。最終測試現象,獲取方法不可控,返回值可能14位也可能15位,使用時很容易導致數據異常。

2、獲取IMEI的常規方式

public static String getIMEI(Context context){
	String imei = "";
	try {
		TelephonyManager tm = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
		if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
			imei = tm.getDeviceId();
		}else {
			Method method = tm.getClass().getMethod("getImei");
			imei = (String) method.invoke(tm);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return imei;
}

3、解決方式

3.1 IMEI的結構

第一部分 TAC,Type Allocation Code,類型分配碼,由8位數字組成(早期是6位), 是區分手機品牌和型號的編碼,該代碼由GSMA及其授權機構分配。其中TAC碼前兩位又是分配機構標識 (Reporting Body Identifier),是授權IMEI碼分配機構的代碼,如01為美國CTIA,35為英國BABT,86為中國TAF。
第二部分 FAC,Final Assembly Code,最終裝配地代碼,由2位數字構成, 僅在早期TAC碼為6位的手機中存在,所以TAC和FAC碼合計一共8位數字。FAC碼用於生產商內部區分生產地代碼。
第三部分 SNR,Serial Number,序列號,由第9位開始的6位數字組成,區分每部手機的生產序列號。
第四部分 CD,Check Digit,驗證碼,由前14位數字通過 Luhn算法計算得出。

由此看出,最后一位是可以直接由前14位計算出來的,那么我們直接判斷長度后再計算一遍就好了。

3.2 Luhn算法

  1. 將偶數位數字分別乘以2,分別計算個位數和十位數之和
  2. 將奇數位數字相加,再加上上一步算得的值
  3. 如果得出的數個位是0則校驗位為0,否則為10減去個位數

如:35 89 01 80 69 72 41

偶數位乘以2得到

5*2=10 、 9*2=18 、 1*2=02 、 0*2=00 、 9*2=18 、 2*2=04 、 1*2=02

計算(奇數位數字)+(上一步計算的偶數位乘積的十位 + 個位),得到

3+(1+0)+8+(1+8)+0+(0+2)+8+(0+0)+6+(1+8)+7+(0+4)+4+(0+2)=63

最后位校驗位為 10-3 = 7

所以完整是358901806972417

3.3 Java實現

public static String getIMEI14To15(String imei) {
	int last = 0, i = 0, temp;
	while (i < imei.length()){
		// 加上奇數位
		result += Integer.parseInt(imei.substring(i, ++i));
		// 偶數位乘以2
		temp = Integer.parseInt(imei.substring(i, ++i)) * 2;
		// 加上偶數位的十位和個位,這里做了優化操作
		// 偶數位乘2的乘積范圍為[0, 18],小於10直接加,大於10則個位與十位的和等於乘積減9
		result += temp < 10 ? temp : temp - 9;
	}
	// 取最終和的個位
	result %= 10;
	// 若為0則為0,否則為10減去個位
	result = result == 0? 0 : 10 - result;
	return imei + result;
}

public static String getIMEI(Context context){
	String imei = "";
	try {
		TelephonyManager tm = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
		if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
			imei = tm.getDeviceId();
		}else {
			Method method = tm.getClass().getMethod("getImei");
			imei = (String) method.invoke(tm);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	if (imei != null && imei.length() == 14) {
		imei = getIMEI14To15(imei);
	}
	return imei;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM