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

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就行了。(但刚开始的时候可能是因为看英文,怎么都没把它们好的联系起来。)

  所将官方的代码改成这样的话就可以查询姓名了。

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
);
  其中游标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所对应的电话就可以了。

  按这个细路就可以写代码了:

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
}
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: