`
quanminchaoren
  • 浏览: 911198 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Android Smart Phone IMEI、IMSI简介

阅读更多

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

Java代码  收藏代码
  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/mydroid/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
从注释里明显看出来这个函数是取SIM卡序列号的,也就是ICCID的,他用错了。

 

Java代码  收藏代码
  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号没有争议了。

 

Java代码  收藏代码
  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()去实现,我们下面找找看。

 

Java代码  收藏代码
  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.     }  

 

Java代码  收藏代码
  1. // 找到了   
  2.     private  IPhoneSubInfo getSubscriberInfo() {  
  3.         // get it each time because that process crashes a lot   
  4.         return  IPhoneSubInfo.Stub.asInterface(ServiceManager.getService( "iphonesubinfo" ));  
  5.     }  
  6.       
  7.     // 一个接口,再找有一个PhoneSubInfo.java:   
  8.     /**  
  9.      * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.  
  10.      */   
  11.     public  String getDeviceId() {  
  12.         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE" );  
  13.         return  mPhone.getDeviceId();  
  14.     }  
  15.   
  16.     //前面定义了Phone mPhone,再找Phone.java:   
  17.     /**  
  18.      * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.  
  19.      */   
  20.     String getSubscriberId();  
  21.   
  22.     //原来是个接口,发现PhoneProxy.java有具体实现      
  23.     public  String getSubscriberId() {  
  24.         return  mActivePhone.getSubscriberId();  
  25.     }  
  26.   
  27.     // 这个mActivePhone是phone的实例,我疯了,于是发现GSMPHONE。java中有了具体实现:   
  28.     public  String getSubscriberId() {  
  29.         return  mSIMRecords.imsi;  
  30.     }  
  31.   
  32.     public  String getIccSerialNumber() {  
  33.         return  mSIMRecords.iccid;  
  34.     }  
  35.   
  36.     public  String getLine1Number()   
  37.    {  
  38.         return  mSIMRecords.getMsisdnNumber();  
  39.    }  

 

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

Java代码  收藏代码
  1. case  EVENT_GET_MSISDN_DONE:  
  2.                 isRecordLoadResponse = true ;  
  3.   
  4.                 ar = (AsyncResult)msg.obj;  
  5.   
  6.                 if  (ar.exception !=  null ) {  
  7.                     Log.d(LOG_TAG, "Invalid or missing EF[MSISDN]" );    //应该是从sim卡的EFmsisdn文件中取出来的   
  8.                     break ;  
  9.                 }  
  10.   
  11.                 adn = (AdnRecord)ar.result;  
  12.   
  13.                 msisdn = adn.getNumber();  
  14.                 msisdnTag = adn.getAlphaTag();  
  15.   
  16.                 Log.d(LOG_TAG, "MSISDN: "  + msisdn);  
  17.             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 楼 hwujo 2011-10-31  
非常好!
android手机的imei能自己去修改吗?

相关推荐

Global site tag (gtag.js) - Google Analytics