Android通讯录查询篇--ContactsContract.Data 二
2011-04-13 19:43
507 查看
上次说Data.MIMETYPE这个玩意很重要,官方的文档中描述了一大段的话。里面比较重要的几点是:
1、在Data中有一大段的公共数据段,DATA1~DATA15。这名子咋一看,真搞笑,哪有这样为数据命名的,神也记不住是干什么的的啊!
2、上面说的那些公共数据段所存的数据类型是由这个MIMETYPE决定的。
虽说这两个重要,不过刚看到这里,我还是懵了,这到底是个什么玩意嘛。(当然这很有可能是因为英文水平差,没看完全懂的原因。)
再看看官方文档,上面有个例子说,如果MIMETYPE的值是Phone.CONTENT_ITEM_TYPE,则DATA1就是电话号码,如果MIMETYPE的值是Email.CONTENT_ITEM_TYPE则DATA1的值就是E-mail地址。这样一说,又似乎明白了点。(还是举实例子来的实在!)
在上次说的那个官方代码里面不就有将MIMETYPE赋值为Phone.CONTENT_ITEM_TYPE的么。所以那个查询就用来查电话了。
在MIMETYPE的描述里面说,它可以被赋许多值:
StructuredName.CONTENT_ITEM_TYPE
Phone.CONTENT_ITEM_TYPE
Email.CONTENT_ITEM_TYPE
Photo.CONTENT_ITEM_TYPE
Organization.CONTENT_ITEM_TYPE
Im.CONTENT_ITEM_TYPE
Nickname.CONTENT_ITEM_TYPE
Note.CONTENT_ITEM_TYPE
StructuredPostal.CONTENT_ITEM_TYPE
GroupMembership.CONTENT_ITEM_TYPE
Website.CONTENT_ITEM_TYPE
Event.CONTENT_ITEM_TYPE
Relation.CONTENT_ITEM_TYPE
现在我们知道的有用Phone那个可以查电话,那用哪个查姓名呢?
再之后看文档时候可以明白把StructuredName.CONTENT_ITEM_TYPE给MINETYPE就行了。(但刚开始的时候可能是因为看英文,怎么都没把它们好的联系起来。)
所将官方的代码改成这样的话就可以查询姓名了。
其中游标C的结果的第二个字段(StructuredName.DISPLAY_NAME)就是姓名,准确的说应该是“显示姓名”(因为姓名也以再细分为姓和名)。
如果还没有理解的话,也不要紧,之后我会把它讲的形像一点。
通讯录虽然不是一个什么难的东西,不过我想还是理顺一点好,免得过些天后又晕了。。
这次主要要做的就是根据姓名来查找电话,并且加强对通讯录的理解。
以前做一些用到数据库的东西的时候,可能光看代码也是不好联系起各个数据之间的关系,所以我先想到的还是数据库。幸运的是,它还真是一个数据库。
Android里面内置的是SQLite的数据库,虽然对数据库不怎么了解,但关系型数据库,基本操作也就那些,而且基本都一样,所以就直接用呗。
用命令行下的adbshell进入Android的模拟器,进入data/data目录下面,这里面就是安装的一些应用程序。找啊找,里面有一个com.android.providers.contacts,怎么看都是一个通讯录相关的程序,进入这个目录下,里面有一个databases,就它了,再进去就可以看到有个contacts2.db的文件。
用sqlite3打开这个数据库文件。查看里面的表。里面表很多,不过看两遍后发现表的名字很熟悉,像什么data,raw_contacts,contacts,minetypes等,前面几个都是我们上次说的那几个所谓的数据模型,它们还真是数据库。
查询一下data表里面的所有信息,可以发现里面的信息联系起来就都是我们通讯录里面的名片。虽然不是一条显示全部,但每个名字每个电话,每个E-mail都有,而且都是分开显示的。现在对于这个应该就有点感觉了。
再看一下表的结构,用”.schema”命令后会看到,类似如下的信息:
.schemadata
CREATETABLEdata(
_idINTEGERPRIMARYKEYAUTOINCREMENT,
package_idINTEGERREFERENCESpackage(_id),
mimetype_idINTEGERREFERENCESmimetype(_id)NOTNULL,
raw_contact_idINTEGERREFERENCESraw_contacts(_id)NOTNULL,
is_primaryINTEGERNOTNULLDEFAULT0,
is_super_primaryINTEGERNOTNULLDEFAULT0,
data_versionINTEGERNOTNULLDEFAULT0,
data1TEXT,
data2TEXT,
data3TEXT,
data4TEXT,
data5TEXT,
data6TEXT,
data7TEXT,
data8TEXT,
data9TEXT,
data10TEXT,
data11TEXT,
data12TEXT,
data13TEXT,
data14TEXT,
data15TEXT,
data_sync1TEXT,
data_sync2TEXT,
data_sync3TEXT,
data_sync4TEXT);
下面还有点索引和触发器的信息就不看了,结合查询的数据看一下。其中“_id”就是表的一个自增id字段。第二个package_id暂时没用到,数据里面全是空。第三个字段minetype_id应该就是MIMETYPE了(其实还是有点不一样的)。后的raw_contact_id就是名片的ID。再看后的data1,data2等字段,每条数据中的这几项都不大相同,准确的说,minetype_id字段不同的数据data1,data2等字段的数据就不同。
现在应该就有一个概念了,以前说的MIMETYPE的值确定Data.DATA1等的值的类型的意思就是在data数据库中通过mimetype_id的值就可以确定data1,data2等字段的真正意义。也就是说在data数据库中通过minetype_id的值可以确定那一条数据到底是存储的姓名,还是电话,还是E-mail或者其它。
这样一来,如果我们要查询某个特定的数据的时候就可以直接查询data表里面的data1,data2这类字段的值,而唯一的必要条件就是在where条件语句里面将minetype_id赋为对应的值。这样就有了一个统一的数据访问方法。而且可以通过这个表查到所以想要的数据。
所以如果想要通过姓名查找一个人的电话就可以这样了,先通过设置MIMETYPE为
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,查找姓名所对应的RAW_CONTACT_ID。再将MIMETYPE设置为
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,查找上面找到的RAW_CONTACT_ID所对应的电话就可以了。
按这个细路就可以写代码了:
PS:
最后再说一下那个MIMETYPE,在data数据库里面它的值是整型,如果看一下官方文档的话,给它所赋的值像
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME之类的都字符串,那么这些字符串和data里面的整型是怎么对应的呢。
其实就是通过mimetypes表来对应的。里面的对应列主要就是9个:
1|vnd.android.cursor.item/email_v2
2|vnd.android.cursor.item/im
3|vnd.android.cursor.item/postal-address_v2
4|vnd.android.cursor.item/photo
5|vnd.android.cursor.item/phone_v2
6|vnd.android.cursor.item/name
7|vnd.android.cursor.item/organization
8|vnd.android.cursor.item/nickname
9|vnd.android.cursor.item/group_membership
1、在Data中有一大段的公共数据段,DATA1~DATA15。这名子咋一看,真搞笑,哪有这样为数据命名的,神也记不住是干什么的的啊!
2、上面说的那些公共数据段所存的数据类型是由这个MIMETYPE决定的。
虽说这两个重要,不过刚看到这里,我还是懵了,这到底是个什么玩意嘛。(当然这很有可能是因为英文水平差,没看完全懂的原因。)
再看看官方文档,上面有个例子说,如果MIMETYPE的值是Phone.CONTENT_ITEM_TYPE,则DATA1就是电话号码,如果MIMETYPE的值是Email.CONTENT_ITEM_TYPE则DATA1的值就是E-mail地址。这样一说,又似乎明白了点。(还是举实例子来的实在!)
在上次说的那个官方代码里面不就有将MIMETYPE赋值为Phone.CONTENT_ITEM_TYPE的么。所以那个查询就用来查电话了。
在MIMETYPE的描述里面说,它可以被赋许多值:
StructuredName.CONTENT_ITEM_TYPE
Phone.CONTENT_ITEM_TYPE
Email.CONTENT_ITEM_TYPE
Photo.CONTENT_ITEM_TYPE
Organization.CONTENT_ITEM_TYPE
Im.CONTENT_ITEM_TYPE
Nickname.CONTENT_ITEM_TYPE
Note.CONTENT_ITEM_TYPE
StructuredPostal.CONTENT_ITEM_TYPE
GroupMembership.CONTENT_ITEM_TYPE
Website.CONTENT_ITEM_TYPE
Event.CONTENT_ITEM_TYPE
Relation.CONTENT_ITEM_TYPE
现在我们知道的有用Phone那个可以查电话,那用哪个查姓名呢?
再之后看文档时候可以明白把StructuredName.CONTENT_ITEM_TYPE给MINETYPE就行了。(但刚开始的时候可能是因为看英文,怎么都没把它们好的联系起来。)
所将官方的代码改成这样的话就可以查询姓名了。
1 | Cursorc=getContentResolver().query(Data.CONTENT_URI, |
2 | new String[]{Data._ID,StructuredName.DISPLAY_NAME,}, |
3 | Data.MIMETYPE+ "='" +StructuredName.CONTENT_ITEM_TYPE+ "'" , |
4 | null , null ); |
如果还没有理解的话,也不要紧,之后我会把它讲的形像一点。
通讯录虽然不是一个什么难的东西,不过我想还是理顺一点好,免得过些天后又晕了。。
这次主要要做的就是根据姓名来查找电话,并且加强对通讯录的理解。
以前做一些用到数据库的东西的时候,可能光看代码也是不好联系起各个数据之间的关系,所以我先想到的还是数据库。幸运的是,它还真是一个数据库。
Android里面内置的是SQLite的数据库,虽然对数据库不怎么了解,但关系型数据库,基本操作也就那些,而且基本都一样,所以就直接用呗。
用命令行下的adbshell进入Android的模拟器,进入data/data目录下面,这里面就是安装的一些应用程序。找啊找,里面有一个com.android.providers.contacts,怎么看都是一个通讯录相关的程序,进入这个目录下,里面有一个databases,就它了,再进去就可以看到有个contacts2.db的文件。
用sqlite3打开这个数据库文件。查看里面的表。里面表很多,不过看两遍后发现表的名字很熟悉,像什么data,raw_contacts,contacts,minetypes等,前面几个都是我们上次说的那几个所谓的数据模型,它们还真是数据库。
查询一下data表里面的所有信息,可以发现里面的信息联系起来就都是我们通讯录里面的名片。虽然不是一条显示全部,但每个名字每个电话,每个E-mail都有,而且都是分开显示的。现在对于这个应该就有点感觉了。
再看一下表的结构,用”.schema”命令后会看到,类似如下的信息:
.schemadata
CREATETABLEdata(
_idINTEGERPRIMARYKEYAUTOINCREMENT,
package_idINTEGERREFERENCESpackage(_id),
mimetype_idINTEGERREFERENCESmimetype(_id)NOTNULL,
raw_contact_idINTEGERREFERENCESraw_contacts(_id)NOTNULL,
is_primaryINTEGERNOTNULLDEFAULT0,
is_super_primaryINTEGERNOTNULLDEFAULT0,
data_versionINTEGERNOTNULLDEFAULT0,
data1TEXT,
data2TEXT,
data3TEXT,
data4TEXT,
data5TEXT,
data6TEXT,
data7TEXT,
data8TEXT,
data9TEXT,
data10TEXT,
data11TEXT,
data12TEXT,
data13TEXT,
data14TEXT,
data15TEXT,
data_sync1TEXT,
data_sync2TEXT,
data_sync3TEXT,
data_sync4TEXT);
下面还有点索引和触发器的信息就不看了,结合查询的数据看一下。其中“_id”就是表的一个自增id字段。第二个package_id暂时没用到,数据里面全是空。第三个字段minetype_id应该就是MIMETYPE了(其实还是有点不一样的)。后的raw_contact_id就是名片的ID。再看后的data1,data2等字段,每条数据中的这几项都不大相同,准确的说,minetype_id字段不同的数据data1,data2等字段的数据就不同。
现在应该就有一个概念了,以前说的MIMETYPE的值确定Data.DATA1等的值的类型的意思就是在data数据库中通过mimetype_id的值就可以确定data1,data2等字段的真正意义。也就是说在data数据库中通过minetype_id的值可以确定那一条数据到底是存储的姓名,还是电话,还是E-mail或者其它。
这样一来,如果我们要查询某个特定的数据的时候就可以直接查询data表里面的data1,data2这类字段的值,而唯一的必要条件就是在where条件语句里面将minetype_id赋为对应的值。这样就有了一个统一的数据访问方法。而且可以通过这个表查到所以想要的数据。
所以如果想要通过姓名查找一个人的电话就可以这样了,先通过设置MIMETYPE为
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,查找姓名所对应的RAW_CONTACT_ID。再将MIMETYPE设置为
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,查找上面找到的RAW_CONTACT_ID所对应的电话就可以了。
按这个细路就可以写代码了:
01 | /** |
02 | *通过姓名(uName)来查找通讯录,返回一个list。其中"display_name"保存姓名,"phone_number"保存电话 |
03 | */ |
04 | public List<HashMap<String,String>>getContactsByName(StringuName){ |
05 | List<HashMap<String,String>>list= new ArrayList<HashMap<String,String>>(); |
06 | boolean isQueryAll= false ; |
07 | //cu姓名游标,cn电话号码游标 |
08 | Cursorcu,cn= null ; |
09 | //查询条件,SQL是的Where语句的后部分 |
10 | Stringselection= null ; |
11 |
12 | uName=uName.trim(); |
13 | //是否查询全部通讯录,如果姓名为空则是 |
14 | isQueryAll=uName.equals( "" )? true : false ; |
15 |
16 | if (isQueryAll){ |
17 | //查询全部时的,查询条件,主要用在cu游标上 |
18 | selection=ContactsContract.Data.MIMETYPE |
19 | + "='" |
20 | +ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE |
21 | + "'" ; |
22 | //System.out.println("QueryForALl--"+selection); |
23 | } else { |
24 | //根据姓名查询时的,查询条件,主要用在cu游标上 |
25 | selection=ContactsContract.Data.MIMETYPE |
26 | + "='" |
27 | +ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE |
28 | + "'" |
29 | + "AND" |
30 | +ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME |
31 | + "LIKE" + "'%" +uName+ "%'" ; |
32 | //System.out.println("QueryForSome--"+selection); |
33 | } |
34 |
35 | try { |
36 | //根据姓名查询出完整姓名和通讯录ID |
37 | cu=contentReso |
38 | .query( |
39 | URI, |
40 | new String[]{ |
41 | ContactsContract.Data.RAW_CONTACT_ID, |
42 | ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME}, |
43 | selection, null , null ); |
44 | //根据通讯录ID,查找对应的电话号码的查询条件,主要用于cn游标 |
45 | selection=ContactsContract.Data.MIMETYPE+ "='" |
46 | +ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE |
47 | + "'" |
48 | + "AND" |
49 | +ContactsContract.Data.RAW_CONTACT_ID |
50 | + "=?" ; |
51 | //System.out.println("NumberQuery--"+selection); |
52 | while (cu.moveToNext()){ |
53 | StringcontactId=String.valueOf(cu.getInt( 0 )); |
54 | //开始查找电话号码 |
55 | //System.out.println("StartQueryNum"); |
56 | cn=contentReso |
57 | .query( |
58 | URI, |
59 | new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER}, |
60 | selection, new String[]{contactId}, null ); |
61 |
62 | while (cn.moveToNext()){ |
63 | //将一组通讯录记录在HashMap中 |
64 | HashMap<String,String>map= new HashMap<String,String>(); |
65 | map.put( "display_name" ,cu.getString( 1 )); |
66 | map.put( "phone_number" ,cn.getString( 0 )); |
67 | //将查到通讯录添加到List中 |
68 | list.add(map); |
69 | } |
70 | } |
71 | //关闭游标 |
72 | cu.close(); |
73 | cn.close(); |
74 | } catch (Exceptione){ |
75 | //TODO:handleexception |
76 | } |
77 | return list; |
78 | } |
79 | } |
最后再说一下那个MIMETYPE,在data数据库里面它的值是整型,如果看一下官方文档的话,给它所赋的值像
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME之类的都字符串,那么这些字符串和data里面的整型是怎么对应的呢。
其实就是通过mimetypes表来对应的。里面的对应列主要就是9个:
1|vnd.android.cursor.item/email_v2
2|vnd.android.cursor.item/im
3|vnd.android.cursor.item/postal-address_v2
4|vnd.android.cursor.item/photo
5|vnd.android.cursor.item/phone_v2
6|vnd.android.cursor.item/name
7|vnd.android.cursor.item/organization
8|vnd.android.cursor.item/nickname
9|vnd.android.cursor.item/group_membership
相关文章推荐
- Android通讯录查询篇--ContactsContract.Data 二
- Android通讯录查询篇--ContactsContract.Data 二
- Android通讯录查询篇--ContactsContract.Data
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二
- Android通讯录查询篇--ContactsContract.Data 二
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android通讯录查询篇--ContactsContract.Data 二(续)
- Android API之android.provider.ContactsContract.Data
- Android API之android.provider.ContactsContract.Data
- 转:android笔记之contacts(通讯录)数据库
- ContactsContract中Contacts,RawContacts和Data关系图解及其实例代码
- android.provider.ContactsContract.Contacts表中所有字段之详解
- Android contacts 联系人 通讯录 源码 完全解析