您的位置:首页 > 移动开发 > Android开发

android 联系人 --- 读取usim卡的邮箱

2013-04-08 16:50 148 查看
本文主要关于usim卡上邮箱地址分析实例的,同时也附带了一个联系人号码的例子,之前分别写过读取sim/usim卡上短信息和联系人信息的文章,偏向代码调用流程,这次把重点放在具体解析过程。本文可以结合下面的链接一起看。

1.android
-- sim/usim卡导联系人
2.android
信息(mms)的故事(七)-- sim卡短信
3.关于sim/usim的一些概念

我们从这里开始 UsimPhoneBookManager.java的内部类PbrFile.java,从卡上读出来的字节数据在这里解析,代码不算多,流程也还清晰,PbrFile.java的构造函数里调用parseTag,parseTag中又调用parseEf,先看下代码再一起分析。下面是具体的代码,

[java]
view plaincopy

private class PbrFile {
HashMap<Integer,Map<Integer,Integer>> mFileIds;

PbrFile(ArrayList<byte[]> records) {
mFileIds = new HashMap<Integer, Map<Integer, Integer>>();
SimTlv recTlv;
int recNum = 0;
for (byte[] record: records) {
recTlv = new SimTlv(record, 0, record.length);
parseTag(recTlv, recNum);
recNum ++;
}
}

void parseTag(SimTlv tlv, int recNum) {
SimTlv tlvEf;
int tag;
byte[] data;
Map<Integer, Integer> val = new HashMap<Integer, Integer>();
do {
tag = tlv.getTag();
switch(tag) {
case USIM_TYPE1_TAG: // A8
case USIM_TYPE3_TAG: // AA
case USIM_TYPE2_TAG: // A9
data = tlv.getData();
tlvEf = new SimTlv(data, 0, data.length);
parseEf(tlvEf, val, tag);
break;
}
} while (tlv.nextObject());
mFileIds.put(recNum, val);
}

void parseEf(SimTlv tlv, Map<Integer, Integer> val, int parentTag) {
int tag;
byte[] data;
int tagNumberWithinParentTag = 0;
do {
tag = tlv.getTag();
if (parentTag == USIM_TYPE2_TAG && tag == USIM_EFEMAIL_TAG) {
mEmailPresentInIap = true;
mEmailTagNumberInIap = tagNumberWithinParentTag;
}
switch(tag) {
case USIM_EFEMAIL_TAG:
case USIM_EFADN_TAG:
case USIM_EFEXT1_TAG:
case USIM_EFANR_TAG:
case USIM_EFPBC_TAG:
case USIM_EFGRP_TAG:
case USIM_EFAAS_TAG:
case USIM_EFGSD_TAG:
case USIM_EFUID_TAG:
case USIM_EFCCP1_TAG:
case USIM_EFIAP_TAG:
case USIM_EFSNE_TAG:
data = tlv.getData();
int efid = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
val.put(tag, efid);
break;
}
tagNumberWithinParentTag ++;
} while(tlv.nextObject());
}

首先看到以new了一个simTlv(simTlv名称来源,3gpp 31.102中 TLV:Tag length value)对象,将传过来的字节数组数组包装了一下,继续往下看在parseTag函数中的switch语句,A8、A9和AA是什么意思呢?和我们读取数组有什么关系呢?读取,清楚这三个tag是我们解析数据的基础,规则如下,

1:USIM卡文件系统内EF文件主要分三类:标签tag为A8的type1类型文件、tag为A9的type2类型文件以及tag为AA的type3类型文件。

2:EFEMAIL(电子邮件)的存在方式只有type1和type2两:当EFEMAIL以type1方式存在时,其中的记录内容和电话本主文件EFADN一对一映射,即EFADN中的第N条记录与EFEMAIL文件中第N条记录一一对应;当EFEMAIL以type2方式存在时,EFADN与EFEMAIL中的记录通过EFIAP文件相关联。EFIAP是type1类型文件,与EFADN中的记录一一对应,EFIAP在文件系统内与type2类型文件必同时存在。
PS:EFEMAIL在文件系统内可能不止一个,且存在方式可能有多种组合。

再接下来在parseEf又出现几个tag,这里我们关注USIM_EFEMAIL_TAG(CA)、USIM_EFADN_TAG(C0)和USIM_EFIAP_TAG(C1),CA标识出电子邮件ID,C0标识的是电话号码ID,C1的作用可以理解一个索引,根据这个索引再去找CA。规则说得差不多了,来看些例子。以标准AT命令(3gpp 27.007)为例

读电子邮件:

1.利用AT命令AT+CRSM=178,20272(EF_PBR:4F30),记录下标,4,0来读取EFPBR文件的记录,获取各个文件的文件ID以及短文件标识SFI。下面是两条USIM卡两条真实的数据记录。

A8 标识

1E 长度(16进制)

C0034F3A01C1034F3102C4034F5A0AC5034F4106C6034F5107C9034F6108

A9 标识

05 长度

CA034F7109

AA14C2034F4A03C7034F4B0BC8034F4C0CCB034F4F16FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

这段就不重复标注了,和上面的一样。
A8

28

C0034F3A04C1034F3105C4034F5A06C4034F6A07C4034F7A08C5034F4109C6034F510AC9034F610B

A9

05

CA034F710C

AA14

C2034F4A0DC7034F4B0EC8034F4C0FCB034F4F10

从此真实记录中看出标识A9下有标识CA(电子邮件),EFEMAIL文件ID为4F71。标识A8下有标识C0(EFADN文件),EFADN文件ID为4F3A,短文件标识为04。标识C1(EFIAP文件)文件ID为4F31。
读得过程中若电子邮件是type1类型文件,则EFEMAIL与EFADN一对一映射,在对应下标处写即可。 如果电子邮件是type2类型文件则:

1)利用AT命令读取此记录对应EFEMAIL文件中的记录下标:

AT+CRSM=178,EFIAP文件ID,对应EFADN文件中的记录下标,4,0

在返回的记录中找到order次序的字段值email_record_index。

2)利用AT命令读取电子邮件文件中email_record_index下标的记录:

AT+CRSM=178,EFEMAIL文件的ID,email_record_index,4,0


针对第二种给出一下例子

[java]
view plaincopy

===>>[Send AT cmd][5] AT+CRSM=178,(4F31)20273,2,4,1,,3F007F105F3A,
<<====[Recv AT cmd][5] +CRSM: 144,0,01,
===>>[Send AT cmd][5] AT+CRSM=178, (4F71)20337,1,4,42,,3F007F105F3A,
<<====[Recv AT cmd][5] +CRSM: 144,0,6775750074792E636F6DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,

到这里故事还没有结束,在上面串里我们看到了EFADN,这家伙指示着电话号码,也许有时候我们还要在去这里找找电话号码,联系人的号码记录是这样

[java]
view plaincopy

===>>[Send AT cmd][5] AT+CRSM=178,20282,1,4,28,,3F007F105F3A, time=Sat Jan 1 08:06:39 2000
<<====[Recv AT cmd][5] +CRSM: 144,0,804E09FFFFFFFFFFFFFFFFFFFFFF0480333333FFFFFFFFFFFFFFFFFF

80、81编码格式,后面紧跟着升序 联系人名字4E09 :三, 号码:3333333(相信聪明的你已经知道80,81代表什么了)。

内容差不多就这些,主要的东西应该都写出来了,导卡这部分给个人的感觉是如果想读全读卡上联系人信息(所有的号码和邮箱)要考虑的东西还是挺多的,流程本身没有多复杂,但是过程比较绕,如果想导卡时间短一些,只导主要的信息就好了(比如忽略附加号码,只找一个邮箱地址),这样能快不少,有些手机确实就是这么做的,不过这种导法从技术的角度是不应该的,对于这种时间与质量的取舍根据项目的具体要求来决定吧。

最后,上面对于 type1类型的电子邮件还没有实例,如果你有欢迎分享一下,当然对文章写得不对地方也欢迎拍砖。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐