關於android讀取使用者號碼,手機串號,SIM卡序列號
阿新 • • 發佈:2019-02-02
1.從一個錯誤程式碼引出我們的討論:
android公開的API提供了訪問方法,大家都知道使用TelephonyManager提供的方法,但是有些理解有誤,如下國內一個比較大的andorid論壇提供的例子,就出現了錯誤:
帖子如下http://www.eoeandroid.com/thread-14027-1-3.html,其中實現程式碼沒有註釋,只能按照變數定義判斷:
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
String deviceid = tm.getDeviceId();
String tel = tm.getLine1Number(); //取出使用者手機號碼,我加的
String imei =tm.getSimSerialNumber(); //取出IMEI,我加的
String imsi =tm.getSubscriberId(); //取出IMSI,我加的
那麼上述出現錯誤了:String imei =tm.getSimSerialNumber(); //取出IMEI
IMEI是手機的序列號,怎麼會通過getSimSerialNumber()方法獲得,那麼查一下andorid原始碼可以看出:
http://www.netmite.com/android/mydroid/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
從註釋裡明顯看出來這個函式是取SIM卡序列號的,也就是ICCID的,他用錯了。
getDeviceId()取IMEI號沒有爭議了。
/**
* Returns the unique device ID, for example,the IMEI for GSM
* phones.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getDeviceId() {
try {
return getSubscriberInfo().getDeviceId();
} catch (RemoteException ex) {
}
return null;
}
getLine1Number()取MSISDN,這個需要說明兩點,1為什麼這個函式叫getLine1Number(),因為andorid實現的時候應該分為GSM和CDMA的,GSM手機使用這個函式,CDMA應該還會由其它實現的。
2取MSISDN具體的方法就會導致最後能否取到了,函式中呼叫了getSubscriberInfo().getLine1Number()去實現,我們下面找找看。
/**
* Returns the phone number string for line 1, for example, the MSISDN
* for a GSM phone.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getLine1Number() {
try {
return getSubscriberInfo().getLine1Number();
} catch (RemoteException ex) {
}
return null;
}
找到了private IPhoneSubInfo getSubscriberInfo() {
// get it each time because that process crashes a lot
return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
}
一個介面,再找有一個PhoneSubInfo.java:
/**
* Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
*/
public String getDeviceId() {
mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
return mPhone.getDeviceId();
}
前面定義了Phone mPhone,再找Phone.java:
/**
* Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
*/
String getSubscriberId();
原來是個介面,發現PhoneProxy.java有具體實現
public String getSubscriberId() {
return mActivePhone.getSubscriberId();
}
這個mActivePhone是phone的例項,我瘋了,於是發現GSMPHONE。java中有了具體實現:
public String getSubscriberId() {
return mSIMRecords.imsi;
}
public String getIccSerialNumber() {
return mSIMRecords.iccid;
}
public String getLine1Number() {
return mSIMRecords.getMsisdnNumber();
從上面看出來,應該是通過SIM卡相關檔案記錄得到的上述資料,從其中看到:
public void handleMessage(Message msg) 這個函式進行了真正的處理,重點看:
case EVENT_GET_MSISDN_DONE:
isRecordLoadResponse = true;
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
Log.d(LOG_TAG, "Invalid or missing EF[MSISDN]"); //應該是從sim卡的EFmsisdn檔案中取出來的
break;
}
adn = (AdnRecord)ar.result;
msisdn = adn.getNumber();
msisdnTag = adn.getAlphaTag();
Log.d(LOG_TAG, "MSISDN: " + msisdn);
break;
下面的細節就不分析了,那個問題就歸結到是否可以從SIM卡的EFmsisdn檔案取出手機號碼了,不幸的是一般運營商不會把使用者號碼寫在這個檔案的,為什麼呢?
因為這個手機號碼是在使用者買到卡並開通時才將IMSI和MSISDN對應上的,卡內生產出來時只有IMSI,你不知道使用者喜歡那個手機號碼,因此一般不先對應IMSI和MSISDN,即時有對應也不寫這個檔案的。
4.總結一下:
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId(); //取出IMEI
String tel = tm.getLine1Number(); //取出MSISDN,很可能為空
String imei =tm.getSimSerialNumber(); //取出ICCID
String imsi =tm.getSubscriberId(); //取出IMSI
android公開的API提供了訪問方法,大家都知道使用TelephonyManager提供的方法,但是有些理解有誤,如下國內一個比較大的andorid論壇提供的例子,就出現了錯誤:
帖子如下http://www.eoeandroid.com/thread-14027-1-3.html,其中實現程式碼沒有註釋,只能按照變數定義判斷:
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
String deviceid = tm.getDeviceId();
String tel = tm.getLine1Number(); //取出使用者手機號碼,我加的
String imei =tm.getSimSerialNumber(); //取出IMEI,我加的
String imsi =tm.getSubscriberId(); //取出IMSI,我加的
那麼上述出現錯誤了:String imei =tm.getSimSerialNumber(); //取出IMEI
IMEI是手機的序列號,怎麼會通過getSimSerialNumber()方法獲得,那麼查一下andorid原始碼可以看出:
http://www.netmite.com/android/mydroid/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
從註釋裡明顯看出來這個函式是取SIM卡序列號的,也就是ICCID的,他用錯了。
/** * Returns the serial number of the SIM, if applicable. * <p> * Requires Permission: * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} */ public String getSimSerialNumber() { try { return3.那好我們看看andorid實現TelephonyManager.java的原始碼:getSubscriberInfo().getSimSerialNumber(); } catch (RemoteException ex) { } return null; } 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手機唯一標識碼;
getDeviceId()取IMEI號沒有爭議了。
/**
* Returns the unique device ID, for example,the IMEI for GSM
* phones.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getDeviceId() {
try {
return getSubscriberInfo().getDeviceId();
} catch (RemoteException ex) {
}
return null;
}
getLine1Number()取MSISDN,這個需要說明兩點,1為什麼這個函式叫getLine1Number(),因為andorid實現的時候應該分為GSM和CDMA的,GSM手機使用這個函式,CDMA應該還會由其它實現的。
2取MSISDN具體的方法就會導致最後能否取到了,函式中呼叫了getSubscriberInfo().getLine1Number()去實現,我們下面找找看。
/**
* Returns the phone number string for line 1, for example, the MSISDN
* for a GSM phone.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getLine1Number() {
try {
return getSubscriberInfo().getLine1Number();
} catch (RemoteException ex) {
}
return null;
}
找到了private IPhoneSubInfo getSubscriberInfo() {
// get it each time because that process crashes a lot
return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
}
一個介面,再找有一個PhoneSubInfo.java:
/**
* Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
*/
public String getDeviceId() {
mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
return mPhone.getDeviceId();
}
前面定義了Phone mPhone,再找Phone.java:
/**
* Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
*/
String getSubscriberId();
原來是個介面,發現PhoneProxy.java有具體實現
public String getSubscriberId() {
return mActivePhone.getSubscriberId();
}
這個mActivePhone是phone的例項,我瘋了,於是發現GSMPHONE。java中有了具體實現:
public String getSubscriberId() {
return mSIMRecords.imsi;
}
public String getIccSerialNumber() {
return mSIMRecords.iccid;
}
public String getLine1Number() {
return mSIMRecords.getMsisdnNumber();
從上面看出來,應該是通過SIM卡相關檔案記錄得到的上述資料,從其中看到:
public void handleMessage(Message msg) 這個函式進行了真正的處理,重點看:
case EVENT_GET_MSISDN_DONE:
isRecordLoadResponse = true;
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
Log.d(LOG_TAG, "Invalid or missing EF[MSISDN]"); //應該是從sim卡的EFmsisdn檔案中取出來的
break;
}
adn = (AdnRecord)ar.result;
msisdn = adn.getNumber();
msisdnTag = adn.getAlphaTag();
Log.d(LOG_TAG, "MSISDN: " + msisdn);
break;
下面的細節就不分析了,那個問題就歸結到是否可以從SIM卡的EFmsisdn檔案取出手機號碼了,不幸的是一般運營商不會把使用者號碼寫在這個檔案的,為什麼呢?
因為這個手機號碼是在使用者買到卡並開通時才將IMSI和MSISDN對應上的,卡內生產出來時只有IMSI,你不知道使用者喜歡那個手機號碼,因此一般不先對應IMSI和MSISDN,即時有對應也不寫這個檔案的。
4.總結一下:
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId(); //取出IMEI
String tel = tm.getLine1Number(); //取出MSISDN,很可能為空
String imei =tm.getSimSerialNumber(); //取出ICCID
String imsi =tm.getSubscriberId(); //取出IMSI