android公开的API提供了访问方法,大家都知道使用TelephonyManager提供的方法,但是有些理解有误,如下国内一个比较大的andorid论坛提供的例子,就出现了错误:
帖子如下http://www.eoeandroid.com/thread-14027-1-3.html,其中实现代码没有注释,只能按照变量定义判断:

Java代码 收藏代码
  1. TelephonyManagertm=(TelephonyManager) this .getSystemService(Context.TELEPHONY_SERVICE);
  2. Stringdeviceid=tm.getDeviceId();
  3. Stringtel=tm.getLine1Number();//取出用户手机号码,我加的
  4. Stringimei=tm.getSimSerialNumber();//取出IMEI,我加的
  5. Stringimsi=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的,他用错了。

Java代码 收藏代码
  1. /**
  2. *ReturnstheserialnumberoftheSIM,ifapplicable.
  3. *<p>
  4. *RequiresPermission:
  5. *{@linkandroid.Manifest.permission#READ_PHONE_STATEREAD_PHONE_STATE}
  6. */
  7. public StringgetSimSerialNumber(){
  8. try {
  9. return getSubscriberInfo().getSimSerialNumber();
  10. }catch (RemoteExceptionex){
  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号没有争议了。

Java代码 收藏代码
  1. /**
  2. *ReturnstheuniquedeviceID,forexample,theIMEIforGSM
  3. *phones.
  4. *
  5. *<p>RequiresPermission:
  6. *{@linkandroid.Manifest.permission#READ_PHONE_STATEREAD_PHONE_STATE}
  7. */
  8. public StringgetDeviceId(){
  9. try {
  10. return getSubscriberInfo().getDeviceId();
  11. }catch (RemoteExceptionex){
  12. }
  13. return null ;
  14. }

getLine1Number()取MSISDN,这个需要说明两点

1) 为什么这个函数叫getLine1Number(),因为andorid实现的时候应该分为GSM和CDMA的,GSM手机使用这个函数,CDMA应该还会由其它实现的。

2) 取MSISDN具体的方法就会导致最后能否取到了,函数中调用了getSubscriberInfo().getLine1Number()去实现,我们下面找找看。

Java代码 收藏代码
  1. /**
  2. *Returnsthephonenumberstringforline1,forexample,theMSISDN
  3. *foraGSMphone.
  4. *<p>
  5. *RequiresPermission:
  6. *{@linkandroid.Manifest.permission#READ_PHONE_STATEREAD_PHONE_STATE}
  7. */
  8. public StringgetLine1Number(){
  9. try {
  10. return getSubscriberInfo().getLine1Number();
  11. }catch (RemoteExceptionex){
  12. }
  13. return null ;
  14. }

Java代码 收藏代码
  1. //找到了
  2. private IPhoneSubInfogetSubscriberInfo(){
  3. //getiteachtimebecausethatprocesscrashesalot
  4. return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService( "iphonesubinfo" ));
  5. }
  6. //一个接口,再找有一个PhoneSubInfo.java:
  7. /**
  8. *RetrievestheuniquedeviceID,e.g.,IMEIforGSMphonesandMEIDforCDMAphones.
  9. */
  10. public StringgetDeviceId(){
  11. mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE,"RequiresREAD_PHONE_STATE" );
  12. return mPhone.getDeviceId();
  13. }
  14. //前面定义了PhonemPhone,再找Phone.java:
  15. /**
  16. *RetrievestheuniquesbuscriberID,e.g.,IMSIforGSMphones.
  17. */
  18. StringgetSubscriberId();
  19. //原来是个接口,发现PhoneProxy.java有具体实现
  20. public StringgetSubscriberId(){
  21. return mActivePhone.getSubscriberId();
  22. }
  23. //这个mActivePhone是phone的实例,我疯了,于是发现GSMPHONE。java中有了具体实现:
  24. public StringgetSubscriberId(){
  25. return mSIMRecords.imsi;
  26. }
  27. public StringgetIccSerialNumber(){
  28. return mSIMRecords.iccid;
  29. }
  30. public StringgetLine1Number()
  31. {
  32. return mSIMRecords.getMsisdnNumber();
  33. }

从上面看出来,应该是通过SIM卡相关文件记录得到的上述数据,从其中看到:
public void handleMessage(Message msg) 这个函数进行了真正的处理,重点看:

Java代码 收藏代码
  1. case EVENT_GET_MSISDN_DONE:
  2. isRecordLoadResponse=true ;
  3. ar=(AsyncResult)msg.obj;
  4. if (ar.exception!= null ){
  5. Log.d(LOG_TAG,"InvalidormissingEF[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 总结

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

更多相关文章

  1. Android 的 dex2jar 和 jd-gui 反编译 apk 源代码
  2. Android Menu详解及示例代码
  3. 在android中利用多线程实现对控件的更新(动态修改文本框中的值)。
  4. 用HTML+JS实现Android闹钟功能,附带Alarm代码分享
  5. Android JUnit Test——批量运行测试代码
  6. 在 Android 使用 Support Annotations 注解优化代码
  7. Android判断网络连接是否可用(代码)
  8. Android中使用代码开关GPS、移动网络(GPRS)、WiFi

随机推荐

  1. Android 获取activity栈中activity
  2. android中文乱码解决大全
  3. Android OTA 系统升级 笔记
  4. Android使用Jsoup解析Html表格的方法
  5. android: 生命周期
  6. Android之TextView------LINK的点击事件
  7. Android获取设备信息(利用反射)
  8. Android(安卓)Studio Gradle 重命名输出A
  9. How to display a custom dialog in your
  10. Android 检测用户一段时间无操作