安卓运营商定制手机锁卡方式研究

为运营商定制的手机,常常需要应运营商的要求对手机网络进行设置。比如,使定制的手机只支持移动的卡,只支持联通或者电信的卡,其他的卡插入无法正常使用手机。甚至只支持上海移动,只支持移动全球通用户。这类手机一般价格比较低,甚至由运营商免费提供给终端用户。为了保证运营商利益,这时就需要对手机的使用范围进行限制,以保证廉价机和赠送机使用在运营商允许的范围内。sim卡是GSM通信协议和3G通信协议的一部分,而做为sim身份标志的imsi号记录了sim使用的国家,运营商,地区,类型,编号等内容。通过对imsi号的过滤能够实现我们控制手机不被应用在非限制的网络上。当然,这不是绝对的,这是可以破解的,普通的刷机就可以消除这个限制,而且通过修改手机文件的方式也是能够破解的。这样的设置也仅仅是增加了破解的难度,有不少的水货手机就是通过重刷定制机流到市场上的。

SIM的结构十分复杂,拥有本身的处理器,存储器和内存。IMSI号是其身份编号,根据GSM通信协议,他们是全球唯一的编号。IMSI号长度定义为15字节。他们使用8个双字节存储,结构如下,第一个双字节存储长度,8个双字节,后面MCC使用两个双字节中的三个字节,长度为三个字节,MNC使用一个双字节和MCC剩余的那个字节,长度为二到三个字节,然后是NSP一个双字节,后面SIM编号:





下面的是通过屏蔽IMSI号的内容,实现网络锁定,如下图:

知道了原理,改起来就容易了,修改的代码位于modem模块,对于MTK,主要文件是配置custom_nvram_sec.c文件,在这个文件中,一定都封闭完毕,sim初始化通过该文件选择启动:


NVRAM_EF_SML_DEFAULT[0]  代表卡1配置,NVRAM_EF_SML_DEFAULT[1]代表卡2配置

 

 constnvram_sml_context_struct NVRAM_EF_SML_DEFAULT[2] =  

//1的配置
{      SML_MAGIC_HEAD_VALUE,
    #ifdefCUSTOM_SML_DEFAULT
        CUSTOM_SML_DEFAULT
    #else /* CUSTOM_SML_DEFAULT*/
        {
 

        /*CategoryN状态由SML_STATE_UNLOCK改为SML_STATE_LOCK,重试次数由SML_RETRY_COUNT_N_CAT改为0

        最后一个参数代表需要锁住的MCC/MNC个数。

       */ 

       {SML_STATE_LOCK,0,0,2}, //{SML_STATE_UNLOCK,SML_RETRY_COUNT_N_CAT,0,0},    /* Category N */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0},   /*Category NS */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_SP_CAT ,0,0},   /*Category SP */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0},    /*Category C */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_SIM_CAT ,0,0},  /* CategorySIM */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0},   /* LinkNS-SP */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0}},    /*Link SIM-C */
       {{SML_KEY_SET,{0x21,0x43,0x65,0x87,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x65,0x87,0x21,0x43,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x11,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_EMPTY,{0x33,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_EMPTY,{0x55,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x77,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x99,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}},
       /* Category N code */
       {
0x46,0x00,0x0F, //BCD
编码,F作补齐用 
        0x46,0x00,0x2F, //BCD
编码,F作补齐用 
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00},
       /* Category NS code */
       {0xc2,0xc2,0xc2,0xc2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},
       /* Category SP code */
       {0xc3,0xc3,0xc3,0xc3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},
       /* Category C code */
       {0xc4,0xc4,0xc4,0xc4,0xc4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00},
       /* Category SIM code */
       {0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
       /* Link Category NS-SP */
       {0xc6,0xc6,0xc6,0xc6,0xc6,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00},  
        /* Link Category SIM-C*/
       {0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
       {0xFF,0xFF},
    #endif /* CUSTOM_SML_DEFAULT*/
       SML_MAGIC_TAIL_VALUE       
}
 

//2的配置

{      SML_MAGIC_HEAD_VALUE,
    #ifdefCUSTOM_SML_DEFAULT
        CUSTOM_SML_DEFAULT
    #else /* CUSTOM_SML_DEFAULT*/
        { 

       {SML_STATE_UNLOCK,SML_RETRY_COUNT_N_CAT,0,0},    /* Category N */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0},   /*Category NS */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_SP_CAT ,0,0},   /*Category SP */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0},    /*Category C */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_SIM_CAT ,0,0},  /* CategorySIM */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0},   /* LinkNS-SP */
       {SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0}},    /*Link SIM-C */
       {{SML_KEY_SET,{0x21,0x43,0x65,0x87,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x65,0x87,0x21,0x43,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x11,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_EMPTY,{0x33,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_EMPTY,{0x55,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x77,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}},
       {SML_KEY_SET,{0x99,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}},
       /* Category N code */
       {
 

        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00},
       /* Category NS code */
       {0xc2,0xc2,0xc2,0xc2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},
       /* Category SP code */
       {0xc3,0xc3,0xc3,0xc3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},
       /* Category C code */
       {0xc4,0xc4,0xc4,0xc4,0xc4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00},
       /* Category SIM code */
       {0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
       /* Link Category NS-SP */
       {0xc6,0xc6,0xc6,0xc6,0xc6,0xFF,0xFF,0xFF,0xFF,0xFF,
        0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00},  
        /* Link Category SIM-C*/
       {0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
       {0xFF,0xFF},
    #endif /* CUSTOM_SML_DEFAULT*/
       SML_MAGIC_TAIL_VALUE       
}
 

}

如果锁中国移动,

{SML_STATE_UNLOCK,SML_RETRY_COUNT_N_CAT,0,0}, 修改为:{SML_STATE_LOCK,0,0,2}, 

该行最后一个参数表示需要锁几个运营商MCC/MNC代码,中国移动有2个,所以填2

还要在CategoryN code 里填写运营商MCC/MNC代码

 

default值的修改一定要包含在对应的宏包起来,以免影响别的项目。

修改这个default值后要将NV项的版本号#defineNVRAM_EF_SML_LID_VERNO升级 

 附:Android SIM/USIM

随着手机的普及,大家从非智能机到智能机的转变,从没有操作系统的定制机到智能手机,但唯一没有变的是,手机中的SIM,今天我们就来谈谈手机中 SIM卡相关的内容。在日常生活中,SIM卡就是一张很小的卡片,但这个卡片上却存储了很重要的信息。  同样,Android作为一个智能手机操作系统,也对SIM卡的读取有相关的操作。下面就以Android2.2的SIM卡读写过程进行讲述。
     在上次博客中,有讲述STK,大家可以点这个链接进行查看。android STK 实现原理 (一)。STK与SIM卡是紧密相关的,讲到STK,不可能不说到SIM卡,下面就回到正题。
    在Android的源码中,SIM卡相关的操作,都封装在framework中,

源码所在的目录

 
 
 
   这个文件夹下,存储了所有与手机通讯业务相关的类文件,其中也包括了SIM,STK,CALL, PS数据业务。在上面的图片中,大家可以看到GSM和CDMA两个文件夹,这也是SIM卡相关的,如果插入的是CDMA卡片,就使用CDMA文件夹中的源 码,如果是2G SIM卡,或是3G 联通卡(即GSM/WCDMA)都是使用GSM文件夹。当打开GSM文件夹,可以看到有一个STK 文件夹,里面装的就是上面那个链接里面的源码。如果是2G SIM卡,或是3G 联通卡(即GSM/WCDMA)都是使用GSM文件夹。当打开GSM文件夹,可以看到有一个STK 文件夹,里面装的就是上面那个链接里面的源码。
和SIM卡相关的类主要有以下几个,
IccConstants  (里面记录很多的常量,主要用来存储某个字段在SIM卡上的位置是什么,比如ADN(sim卡上的电话本),6F3A,  FDN(固定拔号 6F3B)),
IccCardStatus(记录SIM卡的状态,如ABSENT, READY,UNKNOW,ETC),
IccFileHandler(这个是用来SIM卡上的RECORD读完后,要处理什么事情),
IccRecords(SIM卡上的文件内容,每一个字段,一个RECORD),
IccProvider(手机上的数据库,读出来的数据全放这),
IccUtils(里面一般全是静态方法,主要用来码制转换),
IccSmsInterfaceManager,IccCard(这个是一个抽象类,会根据上面手机的制式,自动起一个SIMCARD 或者RUIMCARD).
下面就以GSM为例说下读取的过程,
在GSM中就对应上面说的这些会有自己的类,如
SimCard,
SIMRecords,
SimPhoneBookInterfaceManager,
 
1,手机启动时,
根据SIM卡的类型,进入SIMRecords, 开始探测SIM卡的状态,因为,有些SIM卡会设置有PIN码,如果SIM卡有PIN码的话,手机会弹出输入PIN码的框,等待用户进行解码,注意,这个 时候,如果PIN码如果没有解的话,手机是不会去读SIM卡的,因为,读SIM卡时,必须通过PIN才能去读,只有一些比较特殊的字段,可以不用,比如 ECC 也就是紧急呼叫号码(一般存在卡上,运营商定制的)。同时,这PIN码未解的情况,手机中SIM卡的状态也是PIN_REQURIED_BLOCK,
2,当解完PIN码,或是手机没有设置PIN码,这时,手机的会探测到SIM是READY的状态,手机只有检测到SIM READY,才会发出读卡的请求。
[java] view plaincopy
1. case EVENT_SIM_READY: 
2.                 onSimReady(); 
3.             break; 
4.  
5.     private void onSimReady() { 
6.         /* broadcast intent SIM_READY here so that we can make sure
7.           READY is sent before IMSI ready
8.         */ 
9.         ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent( 
10.                 SimCard.INTENT_VALUE_ICC_READY, null); 
11.  
12.         fetchSimRecords(); 
13. } 
PIN验证通过,会发出一个广播,通知其它的手机应用,SIM卡好了。
[java] view plaincopy
1. private void fetchSimRecords() { 
2.         recordsRequested = true; 
3.         IccFileHandler iccFh = phone.getIccFileHandler(); 
4.  
5.         Log.v(LOG_TAG, "SIMRecords:fetchSimRecords " + recordsToLoad); 
6.  
7.         phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE)); 
8.         recordsToLoad++; 
9.  
10.         iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); 
11.         recordsToLoad++; 
12.  
13.         // FIXME should examine EF[MSISDN]'s capability configuration 
14.         // to determine which is the voice/data/fax line 
15.         new AdnRecordLoader(phone).loadFromEF(EF_MSISDN, EF_EXT1, 1, 
16.                     obtainMessage(EVENT_GET_MSISDN_DONE)); 
17.         recordsToLoad++; 
18.  
19.         // Record number is subscriber profile 
20.         iccFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE)); 
21.         recordsToLoad++; 
22.  
23.         iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); 
24.         recordsToLoad++; 
25.  
26.         // Record number is subscriber profile 
27.         iccFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE)); 
28.         recordsToLoad++; 
29.  
30.  
31.         // Also load CPHS-style voice mail indicator, which stores 
32.         // the same info as EF[MWIS]. If both exist, both are updated 
33.         // but the EF[MWIS] data is preferred 
34.         // Please note this must be loaded after EF[MWIS] 
35.         iccFh.loadEFTransparent( 
36.                 EF_VOICE_MAIL_INDICATOR_CPHS, 
37.                 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE)); 
38.         recordsToLoad++; 
39.  
40.         // Same goes for Call Forward Status indicator: fetch both 
41.         // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred. 
42.         iccFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE)); 
43.         recordsToLoad++; 
44.         iccFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE)); 
45.         recordsToLoad++; 
46.  
47.  
48.         getSpnFsm(true, null); 
49.  
50.         iccFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE)); 
51.         recordsToLoad++; 
52.  
53.         iccFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE)); 
54.         recordsToLoad++; 
55.  
56.         iccFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE)); 
57.         recordsToLoad++; 
58.  
59.         iccFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE)); 
60.         recordsToLoad++; 
61.  
62.         // XXX should seek instead of examining them all 
63.         if (false) { // XXX 
64.             iccFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE)); 
65.             recordsToLoad++; 
66.         } 
67.  
68.         if (CRASH_RIL) { 
69.             String sms = "0107912160130310f20404d0110041007030208054832b0120" 
70.                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 
71.                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 
72.                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 
73.                          + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 
74.                          + "ffffffffffffffffffffffffffffff"; 
75.             byte[] ba = IccUtils.hexStringToBytes(sms); 
76.  
77.             iccFh.updateEFLinearFixed(EF_SMS, 1, ba, null, 
78.                             obtainMessage(EVENT_MARK_SMS_READ_DONE, 1)); 
79.         } 
80.     } 

这里,手机开始读卡第一个是
IMSI(International Mobile SubscriberIdentification Number)主要用来查找运营商的网络,里面有MCC,MNC,
ICCID(Integrate circuit card identity)唯一标识一个移动用户。
然后,大家可以看到有很多类似这样的函数调用iccFh.loadEFTransparent,这个就是调用IccFileHandler,读取SIM卡字段
[java] view plaincopy
1. public void loadEFTransparent(int fileid, Message onLoaded) { 
2.         Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE, 
3.                         fileid, 0, onLoaded); 
4.  
5.         phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 
6.                         0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response); 
7.     } 
大家注意到phone.mCM.iccIO,这个东东就是我们的RIL.JAVA, 向低层的MODEM 发送一个读取SIM卡的命令,在RIL.JAVA 中。Fileid 是字段的地址,如上面说的AND(在这为6F3A),FDN(在这为6F3B).
3.当低层的MODEM读到字段结果后,会有一个返回结果,由于发送读取请求时,有一个事件信息EVENT_GET_BINARY_SIZE_DONE,当有返回时,会直接交给IccFileHandler,然后由IccFileHandler转发给SIMRecords,最后进行处理该字段读完后应该执行的操作。由RIL.JAVA通知IccFileHandler,处理如下
[java] view plaincopy
1. case EVENT_GET_BINARY_SIZE_DONE: 
2.                ar = (AsyncResult)msg.obj; 
3.                response = (Message) ar.userObj; 
4.                result = (IccIoResult) ar.result; 
5.  
6.                if (ar.exception != null) { 
7.                    sendResult(response, null, ar.exception); 
8.                    break; 
9.                } 
10.  
11.                iccException = result.getException(); 
12.  
13.                if (iccException != null) { 
14.                    sendResult(response, null, iccException); 
15.                    break; 
16.                } 
17.  
18.                data = result.payload; 
19.  
20.                fileid = msg.arg1; 
21.  
22.                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) { 
23.                    throw new IccFileTypeMismatch(); 
24.                } 
25.  
26.                if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) { 
27.                    throw new IccFileTypeMismatch(); 
28.                } 
29.  
30.                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8) 
31.                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff); 
32.  
33.                phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid), 
34.                                0, 0, size, null, null, 
35.                                obtainMessage(EVENT_READ_BINARY_DONE, 
36.                                              fileid, 0, response)); 
37.            break; 
回到SIMRecords,处理ICCID读完后相关操作,代码如下:
[java] view plaincopy
1. case EVENT_GET_ICCID_DONE: 
2.                 isRecordLoadResponse = true; 
3.  
4.                 ar = (AsyncResult)msg.obj; 
5.                 data = (byte[])ar.result; 
6.  
7.                 if (ar.exception != null) { 
8.                     break; 
9.                 } 
10.  
11.                 iccid = IccUtils.bcdToString(data, 0, data.length); 
12.  
13.                 Log.d(LOG_TAG, "iccid: " + iccid); 
14.  
15.             break; 

 
到此,一个完整的SIM卡读取过程就完成了。
PS:有可能有人会问,为什么有时候是
iccFh.loadEFTransparent
有时候是
iccFh.loadEFLinearFixed
这主要是跟所要读取EF的类型有关系,SIM卡上的文件类型有Elementary File, Delicated File, Cyclic File,其中EF又分为Linear fixed EF,Transparent EF,Cyclic EF,所以读取的方式是不一样的,可能参考3GPP 11.11,  3GPP 51.011.
OK, 累了,有什么问题,可以在下面问,


参考:
http://blog.csdn.net/jiangyu912/article/details/5738984
http://blog.csdn.net/guoleimail/article/details/7082156
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值