android讀取手機號碼/串號/SIM卡序列號

1.從一個錯誤代碼引出我們的討論:
android公開的API提供了訪問方法,大家都知道使用TelephonyManager提供的方法,但是有些理解有誤,如下國內一個比較大的andorid論壇提供的例子,就出現了錯誤:
帖子如下http://www.eoeandroid.com/thread-14027-1-3.html,其中實現代碼沒有註釋,只能按照變量定義判斷:

  1.         TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
  2.         String deviceid = tm.getDeviceId(); 
  3.         String tel = tm.getLine1Number();     //取出用戶手機號碼,我加的
  4.         String imei =tm.getSimSerialNumber();  //取出IMEI,我加的
  5.         String imsi =tm.getSubscriberId();     //取出IMSI,我加的
複製代碼

那麼上述出現錯誤了:String imei =tm.getSimSerialNumber();  //取出IMEI
IMEI是手機的序列號,怎麼會通過getSimSerialNumber()方法獲得,那麼查一下andorid源碼可以看出:
http://www.netmite.com/android/m ... lephonyManager.java
從註釋裡明顯看出來這個函數是取SIM卡序列號的,也就是ICCID的,他用錯了。

  1.     /**
  2.      * Returns the serial number of the SIM, if applicable.
  3.      * <p>
  4.      * Requires Permission: 
  5.      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
  6.      */
  7.     public String getSimSerialNumber() {
  8.         try {
  9.             return getSubscriberInfo().getSimSerialNumber();
  10.         } catch (RemoteException ex) {
  11.         }
  12.         return null;
  13.     }
複製代碼

2.相關幾個定義、說明:
我們說到的和手機、卡相關的號碼數據包括IMSI,MSISDN,ICCID,IMEI
IMSI:international mobiles subscriber identity國際移動用戶號碼標識,
這個一般大家是不知道,GSM必須寫在卡內相關文件中;
MSISDN:mobile subscriber ISDN用戶號碼,這個是我們說的139,136那個號碼;
ICCID:ICC identity集成電路卡標識,這個是唯一標識一張卡片物理號碼的;
IMEI:international mobile Equipment identity手機唯一標識碼;
3.那好我們看看andorid實現TelephonyManager.java的源碼:
getDeviceId()取IMEI號沒有爭議了。

  1. /**
  2.      * Returns the unique device ID, for example,the IMEI for GSM
  3.      * phones.
  4.      *
  5.      * <p>Requires Permission: 
  6.      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
  7.      */
  8.     public String getDeviceId() {
  9.         try {
  10.             return getSubscriberInfo().getDeviceId();
  11.         } catch (RemoteException ex) {
  12.         }
  13.         return null;
  14.     }
複製代碼

getLine1Number()取MSISDN,這個需要說明兩點,1為什麼這個函數叫getLine1Number(),因為andorid實現的時候應該分為GSM和CDMA的,GSM手機使用這個函數,CDMA應該還會由其它實現的。
2取MSISDN具體的方法就會導致最後能否取到了,函數中調用了getSubscriberInfo().getLine1Number()去實現,我們下面找找看。

  1. /**
  2.      * Returns the phone number string for line 1, for example, the MSISDN 
  3.      * for a GSM phone.
  4.      * <p>
  5.      * Requires Permission: 
  6.      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
  7.      */
  8.     public String getLine1Number() {
  9.         try {
  10.             return getSubscriberInfo().getLine1Number();
  11.         } catch (RemoteException ex) {
  12.         }
  13.         return null;
  14.     }
複製代碼

找到了

  1. private IPhoneSubInfo getSubscriberInfo() {
  2.         // get it each time because that process crashes a lot
  3.         return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
  4.     }
複製代碼

一個接口,再找有一個PhoneSubInfo.java:

  1.     /**
  2.      * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
  3.      */
  4.     public String getDeviceId() {
  5.         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
  6.         return mPhone.getDeviceId();
  7.     }
複製代碼

前面定義了Phone mPhone,再找Phone.java:

  1.   /**
  2.      * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
  3.      */
  4.     String getSubscriberId();
複製代碼

原來是個接口,發現PhoneProxy.java有具體實現

  1. public String getSubscriberId() {
  2.         return mActivePhone.getSubscriberId();
  3.     }
複製代碼

這個mActivePhone是phone的實例,我瘋了,於是發現GSMPHONE。java中有了具體實現:

  1.    public String getSubscriberId() {
  2.         return mSIMRecords.imsi;
  3.     }

  4.     public String getIccSerialNumber() {
  5.         return mSIMRecords.iccid;
  6.     }

  7.     public String getLine1Number() {
  8.         return mSIMRecords.getMsisdnNumber();
複製代碼

從上面看出來,應該是通過SIM卡相關文件記錄得到的上述數據,從其中看到:
public void handleMessage(Message msg) 這個函數進行了真正的處理,重點看:

  1. case EVENT_GET_MSISDN_DONE:
  2.                 isRecordLoadResponse = true;

  3.                 ar = (AsyncResult)msg.obj;

  4.                 if (ar.exception != null) {
  5.                     Log.d(LOG_TAG, "Invalid or missing EF[MSISDN]");   //應該是從sim卡的EFmsisdn文件中取出來的
  6.                     break;
  7.                 }

  8.                 adn = (AdnRecord)ar.result;

  9.                 msisdn = adn.getNumber();
  10.                 msisdnTag = adn.getAlphaTag();

  11.                 Log.d(LOG_TAG, "MSISDN: " + msisdn);
  12.             break;
複製代碼

下面的細節就不分析了,那個問題就歸結到是否可以從SIM卡的EFmsisdn文件取出手機號碼了,不幸的是一般運營商不會把用戶號碼寫在這個文件的,為什麼呢?
因為這個手機號碼是在用戶買到卡並開通時才將IMSI和MSISDN對應上的,卡內生產出來時只有IMSI,你不知道用戶喜歡那個手機號碼,因此一般不先對應IMSI和MSISDN,即時有對應也不寫這個文件的。

4.總結一下:

  1. TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
  2.         String imei = tm.getDeviceId();       //取出IMEI
  3.         String tel = tm.getLine1Number();     //取出MSISDN,很可能為空
  4.         String imei =tm.getSimSerialNumber();  //取出ICCID
  5.         String imsi =tm.getSubscriberId();     //取出IMSI
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值