`

android 通讯录

 
阅读更多

转载http://www.cnblogs.com/3dant/archive/2010/12/08/1900634.html

 

  Android刚开始在通讯录方面好像是提供的Contacts这个类,又在SDK2.0发布后新加了一个ContactsContract,然后就不建议用Contacts这个旧的类了。有新的东西,当然要用新的了。

  对于ContactsContact官方文档里面说它是基于一个三层的数据模型存储的,个人的一个大致的理解就是,它是由三个主要的数据库组成的。这三个数据模型就是以ContactsContact.Data,ContactsContact.RawContacts,ContactsContact.Contacts。

  三个模型的功能大致为,

  Data:存储通讯录中每个人的全部信息,什么名字,电话,E-mail等一些乱七八糟和东西全在里面。

  RawContacts:这个里面好像是说存储的是个人描述信息和一些唯一确定的相关的帐号

  Contacts:这个好像是通讯录里面的一个人的基本描述,像什么显示的名字,分组情况,有没有电话号码之类的了。

  反正后面两个搞的真是懵懵的,我先不管这两个了。因为Data里面说它包括通讯录里每个人的全部信息,以理论上说对通讯录的全部操作都可以用这个来搞定。所以我也是选的它,降低难度嘛。

  关于Data,看一下文档里面的详细内容,里面主要说了一个“数据类型”(Data kinds),对应的是Data.MIMETYPE这个列。我们还是先不管这个,之后再说。我刚用的时候对它还很是纠结了一把。

  Data里面也是含有对数据的“增删改查”四个基本操作,看到这里基本可以确定它肯定是一个数据库了。官方每个操作都提供了一些事例代码。第一次玩当然是从简单的“查”来入手了。

  官方给的代码有两个,我主要看的第二个,因在后面的官方描述中CONTACT_ID好像就是RAW_CONTACT_ID:

 

1 Cursor c = getContentResolver().query(Data.CONTENT_URI,
2           new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},
3           Data.RAW_CONTACT_ID + "=?" + " AND "
4                   + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'",
5           new String[] {String.valueOf(rawContactId)}, null);

 

 

  这个代码里面一般至少都能意会出它是在做什么。就是通过联系人ID查找他的电话号码,电话类型,和电话标签。像里的Data._ID中的Data就是ContactsContact.Data,Phone.TYPE里面的Phone就是ContactsContract.CommonDataKinds.Phone。

  通过上面的代码我们可以知道,要查找一个通讯录可以通过ContentResolver的query()方法来查找,最终返回一个游标Cursor,通过Cursor的get***方法就可以把想要的数据读出来了。关于query方法,可以说就一个生成一相格式化SQL语句的方法。它有五个参数,简单的理解就是(uri相当于要查询的表名,你要查询哪几个字段用String数组表示,查询条类似Where后面的部分,如果前面的参数里面有?的点位符这个参数就是它对应的值,排序)。

  看了这个代码有点查询通讯录的概念了,不过现在可能有人就有问题要问了,官方的代码里面怎么不把联系人的姓名查出来,因为就算我们不懂代码,单看英文怎么也没有Name这类的单词啊。查联系人怎么说也要有名字有电话,不然要它干什么。是不是官方太懒了多加个字段不行么?

   上次说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 Cursor c = 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)就是姓名,准确的说应该是“显示姓名”(因为姓名也以再细分为姓和名)。

      如果还没有理解的话,也不要紧,之后我会把它讲的形像一点。通讯录虽然不是一个什么难的东西,不过我想还是理顺一点好

 

      这次主要要做的就是根据姓名来查找电话,并且加强对通讯录的理解。

  以前做一些用到数据库的东西的时候,可能光看代码也是不好联系起各个数据之间的关系,所以我先想到的还是数据库。用命令行下的adb  shell进入Android的模拟器,进入data/data目录下面,这里面就是安装的一些应用程序。找啊找,里面有一个com.android.providers.contacts,怎么看都是一个通讯录相关的程序,进入这个目录下,里面有一个databases,就它了,再进去就可以看到有个contacts2.db的文件。

  用sqlite3打开这个数据库文件。查看里面的表。里面表很多,不过看两遍后发现表的名字很熟悉,像什么data,raw_contacts,contacts,minetypes等,前面几个都是我们上次说的那几个所谓的数据模型,它们还真是数据库。

  

  查询一下data表里面的所有信息,可以发现里面的信息联系起来就都是我们通讯录里面的名片。虽然不是一条显示全部,但每个名字每个电话,每个E-mail都有,而且都是分开显示的。现在对于这个应该就有点感觉了。

  

  再看一下表的结构,用”.schema” 命令后会看到,类似如下的信息:

.schema data

CREATE TABLE data (

_id INTEGER PRIMARY KEY AUTOINCREMENT,

package_id INTEGER REFERENCES package(_id),

mimetype_id INTEGER REFERENCES mimetype(_id) NOT NULL,

raw_contact_idINTEGER REFERENCES raw_contacts(_id) NOT NULL,

is_primary INTEGER NOT NULL DEFAULT 0,

is_super_primary INTEGER NOT NULL DEFAULT 0,

data_version INTEGER NOT NULL DEFAULT 0,

data1 TEXT,

data2 TEXT,

data3 TEXT,

data4 TEXT,

data5 TEXT,

data6 TEXT,

data7 TEXT,

data8 TEXT,

data9 TEXT,

data10 TEXT,

data11 TEXT,

data12 TEXT,

data13 TEXT,

data14 TEXT,

data15 TEXT,

data_sync1 TEXT,

 data_sync2 TEXT,

 data_sync3 TEXT,

 data_sync4 TEXT );

 

  下面还有点索引和触发器的信息就不看了,结合查询的数据看一下。其中“_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(String uName) {
05         List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
06         boolean isQueryAll = false;
07         // cu姓名游标,cn电话号码游标
08         Cursor cu, cn = null;
09         // 查询条件,SQL是的Where语句的后部分
10         String selection = 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("Query For ALl--" + 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("Query For Some--" + 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("Number Query--" + selection);
52             while (cu.moveToNext()) {
53                 String contactId = String.valueOf(cu.getInt(0));
54                 // 开始查找电话号码
55                 //System.out.println("  Start Query Num");
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 (Exception e) {
75             // TODO: handle exception
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

 

下面有个附件测试通讯录

分享到:
评论

相关推荐

    Android通讯录附搜索及字母索引Demo

    这个"Android通讯录附搜索及字母索引Demo"项目旨在提供一个示例,帮助开发者理解和实现类似原生Android系统通讯录的功能,包括联系人搜索和字母索引。下面我们将深入探讨其中涉及的关键知识点。 1. **SQLite数据库*...

    Android通讯录的开发-完整代码

    以上就是基于标题“Android通讯录的开发-完整代码”和描述“Android]通讯录的开发_完整代码,项目可直接运行,欢迎下载学习”的主要技术知识点。通过学习和实践这个项目,开发者可以深入了解Android应用开发的各个...

    使用android通讯录中的内容提供者实例

    在这个实例中,我们将深入探讨如何使用Android通讯录的内容提供者来查询和添加联系人。 一、Android内容提供者基础 内容提供者是一个实现了ContentProvider类的组件,它负责存储、检索以及更新应用程序的数据。每个...

    android通讯录

    Android 通讯录小软件开发 本资源是一个 Android 通讯录小软件的开发实践,包括了 Android 通讯录的开发、 SQLite 数据库的使用、联系人信息的存储和管理等方面的知识点。 一、Android 通讯录的开发 Android ...

    android通讯录(完整,可运行)

    《Android通讯录系统详解——基于adt-bundle-windows的实现》 在移动设备上,通讯录是用户日常使用的重要功能之一。Android系统以其开放性和灵活性,为开发者提供了丰富的API,使得开发自定义通讯录应用成为可能。...

    Android通讯录源码.rar

    【Android通讯录源码分析】 本项目是一款基于Android平台的通讯录应用,它不仅提供了基本的本地联系人存储和检索功能,还集成了拨打电话和发送短信的能力,非常适合用于学习和理解Android应用开发中的核心概念和...

    android 通讯录(A-Z)带可模糊查询搜索框

    在Android开发中,实现一个完整的通讯录功能是一个常见的需求,涉及到很多关键的技术点。这篇教程“android 通讯录(A-Z)带可模糊查询搜索框”着重讲解如何创建一个能够进行字母索引排序和模糊查询的通讯录界面。在...

    Android通讯录的源代码

    【Android通讯录源代码解析】 在移动设备上,通讯录是一个至关重要的功能,它帮助用户存储、管理和查找联系人的信息。本项目是基于Java语言开发的Android通讯录应用,提供了全面的通讯录功能,旨在帮助开发者理解...

    自己做的android通讯录

    这个“自己做的android通讯录”项目,显然是一个初学者为了掌握Android编程而创建的。它涉及到的关键知识点包括Android应用的基本架构、数据存储、用户界面设计以及事件处理。 首先,Android应用的基本架构通常包含...

    Android通讯录源代码

    【Android通讯录源代码】是Android平台上实现联系人管理功能的一种源码实现,它涉及到Android系统的核心组件和服务,包括数据库操作、UI设计、数据存储和检索等关键知识点。在这个源码中,我们可以深入理解Android...

    Android通讯录.zip

    《Android通讯录项目详解》 在移动开发领域,Android平台上的通讯录管理是不可或缺的一部分,它涉及到用户数据的存储、查询、更新以及删除等操作。本篇将详细探讨基于Android的通讯录项目,主要涉及的技术点包括...

    仿android通讯录demo

    【仿android通讯录demo】是一个基于Android平台的项目,旨在实现与原生Android系统通讯录类似的功能。这个项目的核心目标是提供一个用户友好的界面,让用户能够方便地按字母顺序浏览联系人,进行搜索,并在顶部看到...

    android 通讯录(注释完整)

    1. 数据存储:Android通讯录通常使用SQLite数据库来存储联系人信息。SQLite是轻量级的、嵌入式的关系型数据库,它允许开发者在应用中执行SQL语句,进行数据的增删改查。创建一个Contact表,包含姓名、电话号码、电子...

    android通讯录程序的实现.rar

    这个压缩包“android通讯录程序的实现.rar”显然包含了实现这样一个程序的所有源代码和相关说明,非常适合初学者或者对Android编程感兴趣的开发者学习。下面我们将深入探讨这个项目可能包含的知识点。 首先,通讯录...

    android通讯录左侧滑动搜索效果

    "android通讯录左侧滑动搜索效果"是一个常见的功能,它允许用户通过简单的手势在通讯录中快速查找联系人,提高了查找效率。这个DEMO提供了这样的功能实现,让用户能够通过在屏幕左侧滑动来激活搜索栏。 首先,我们...

    android 通讯录 电话本按字母排序即时搜索

    在Android平台上,构建一个高效的通讯录应用是许多开发者面临的一项挑战。这个项目“android 通讯录 电话本按字母排序即时搜索”旨在模仿QQ通讯录的功能,为用户提供友好的用户体验,包括右侧按字母索引的分类,按...

    android通讯录简单项目源码

    本文将深入探讨这些技术要点,以便你更好地理解这个"android通讯录简单项目源码"。 首先,我们要了解Android应用的基本结构。一个标准的Android应用由多个组件构成,包括Activity(活动)、Service(服务)、...

    Android通讯录_字母导航_字母悬浮

    总的来说,Android通讯录的字母导航和字母悬浮功能是提高用户交互体验的关键,它们涉及到Android系统的数据展示、触摸事件处理、UI设计等多个方面。开发者需要对Android的基础组件和接口有深入理解,才能有效地实现...

    Android通讯录源码

    这份"Android通讯录源码"提供了一个实现这一功能的实例,让我们来深入探讨其中的关键技术。 1. **Android UI 设计**:在Android应用中,通讯录通常使用ListView或RecyclerView来显示联系人列表。这些组件允许动态...

Global site tag (gtag.js) - Google Analytics