關於IMEI、MEID、IMSI

關於IMEI、MEID、IMSI

簡介

IMEI、MEID都是用於標識一臺物理設備的ID信息。在Android 8.0以下系統提供的API中,會根據不同條件返回二者之一的信息。

  • IMEI: 國際移動設備識別碼,是區別移動設備的標誌,一般用於標識某一臺獨立的設備,雙卡雙待的手機有兩個IMEI號。
    格式:15位十進制數
  • MEID: 同樣也是移動設備標識碼,但一般用於CDMA制式的設備上,是ESN碼的升級版,只有一個MEID
    格式:14位十六進制數

API

1、SDK26開始,TelephonyManager提供了兩個獨立的API以獲取IMEI和MEID: getImei 、 getMeid 。兩個API都可傳入下標號獲取多個設備號信息,getImei(0)獲取卡一的IMEI,getImei(1)獲取卡二的IMEI,和SIM卡放在什麼位置沒有關係,和是哪個運營商的也沒有關係,沒有SIM卡也可以獲取IMEI,getImei()方法獲取的IMEI就是卡一的IMEI,卡槽的IMEI是固定的,驗證機型小米5S,華爲P30,華爲Mate10,電信移動卡

/**
     * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
     * available.
     *
     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
     *
     * @param slotIndex of which IMEI is returned
     */
    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    public String getImei(int slotIndex) {
        ITelephony telephony = getITelephony();
        if (telephony == null) return null;

        try {
            return telephony.getImeiForSlot(slotIndex, getOpPackageName());
        } catch (RemoteException ex) {
            return null;
        } catch (NullPointerException ex) {
            return null;
        }
    }

2、SDK26以下的系統獲取IMEI或MEID的API爲TelephonyManager.getDeviceId(),若當前設備有MEID號,則優先返回MEID,否則返回IMEI號。則獲取到的設備ID需要通過長度判斷才能知曉該ID爲IMEI還是MEID,會存在IMEI獲取不到,只能獲取MEID的情況。 比如用戶插移動聯通的卡,返回imei1,imei2,插電信的卡就變成返回imei1,meid了 (PS:這個我沒有驗證網上博客有人這麼寫)

SDK26以下:谷歌官方把getImei這個獲取IMEI的單獨API隱藏起來了,不知道爲啥,,如果要調用可以利用反射


 
    /**
     * Returns the IMEI. Return null if IMEI is not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     *
     * @param slotId of which deviceID is returned
     */
    /** {@hide} */  SDK26以下的版本加了個隱藏的註解!!
    public String getImei(int slotId) {
        ITelephony telephony = getITelephony();
        if (telephony == null) return null;
 
        try {
            return telephony.getImeiForSlot(slotId, getOpPackageName());
        } catch (RemoteException ex) {
            return null;
        } catch (NullPointerException ex) {
            return null;
        }
    }

我們公版項目裏只用了getDeviceId這個過時的方法來獲取IMEI,照理是會存在問題,但是如果只是作爲唯一標識的話,獲取到的是IMEI還是MEID沒差。。。我們只獲取IMEI,不獲取MEID

 /**
     * Returns the unique device ID of a subscription, for example, the IMEI for
     * GSM and the MEID for CDMA phones. Return null if device ID is not available.
     *
     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
     *
     * @param slotIndex of which deviceID is returned
     *
     * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
     * MEID for CDMA.
     */
    @Deprecated    SDK28 已經把這個方法標成不推薦使用了。。。!!
    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    public String getDeviceId(int slotIndex) {
        // FIXME this assumes phoneId == slotIndex
        try {
            IPhoneSubInfo info = getSubscriberInfo();
            if (info == null)
                return null;
            return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName());
        } catch (RemoteException ex) {
            return null;
        } catch (NullPointerException ex) {
            return null;
        }
    }

關於IMSI,和SIM卡綁定,,雙卡手機,getSubscriberId方法不傳參讀的是主卡的IMSI,當主卡斷網或者手動把主卡設置成另一張卡時,讀的就是另一張卡的IMSI,和卡槽沒有關係,只和當前用的是哪張卡有關係,如圖,主副卡切換時讀取的IMSI變化,IMEI不變化

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