關注微信公衆號:程序員小安,精彩文章按期推送。android
獲取IMEI相信你們很是熟悉,可是項目中使用時,發現當手機卡爲電信的時候,獲取的並非IMEI,而是MEID,什麼是MEID,爲何會出現這種狀況呢? IMEI國際移動設備識別碼(IMEI:International Mobile Equipment Identification Number)是區別移動設備的標誌,儲存在移動設備中,可用於監控被竊或無效的移動設備。目前GSM和WCDMA手機終端須要使用IMEI號碼 MEID移動設備識別碼(Mobile Equipment Identifier)是CDMA手機的身份識別碼,也是每臺手機有惟一的識別碼。經過這個識別碼,網絡端能夠對該手機進行跟蹤和監管。用於CDMA制式的手機。MEID的數字範圍是十六進制的,和IMEI的格式相似。程序員
爲何會出現獲取的不是IMEI,而是MEID呢,繼續往下看。 通常狀況下,你們獲取imei號,經過如下兩個步驟實現。 1)添加讀取權限:bash
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 複製代碼
2)獲取設備imei號微信
public static String getImei(Context context) { TelephonyManager telephonyMgr = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE); String imei = telephonyMgr.getDeviceId(); return imei ; } 複製代碼
很明顯,經過調用getDeviceId()但願獲取IMEI,可是獲得的倒是MEID,定位到getDeviceId()的源碼,以下:markdown
/** * Returns the unique device ID, for example, the IMEI for GSM and the MEID * or ESN for CDMA phones. Return null if device ID is not available. * * <p>Requires Permission: * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} */ public String getDeviceId() { try { ITelephony telephony = getITelephony(); if (telephony == null) return null; return telephony.getDeviceId(mContext.getOpPackageName()); } catch (RemoteException ex) { return null; } catch (NullPointerException ex) { return null; } } 複製代碼
註釋很明顯了,CDMA手機返回的是MEID或者ESN,也就是電信卡返回的是MEID,到這裏咱們發現了問題所在,那麼如何解決呢,瀏覽源碼,咱們發現,有個隱藏的(hide)方法,以下:網絡
/** * Returns the IMEI. Return null if IMEI is not available. * * <p>Requires Permission: * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} */ /** {@hide} */ public String getImei() { return getImei(getDefaultSim()); } 複製代碼
這個方法能夠獲取IMEI,可是因爲是hide方法,不能直接調用,因此咱們只能經過反射調用該方法。ide
代碼很簡單,以下所示:學習
public static String getMachineImei(Context context) { TelephonyManager manager = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE); Class clazz = manager.getClass(); String imei = ""; try { Method getImei=clazz.getDeclaredMethod("getImei",int.class);//(int slotId) getImei.setAccessible(true); imei = (String) getImei.invoke(manager); } catch (Exception e) { } return imei; } 複製代碼
經過上述反射調用getImei(),則能夠在電信卡手機成功獲取IMEI號,當前前提是存在IMEI號。ui
若有錯誤歡迎指出來,一塊兒學習。 spa