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

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

  三个模型的功能大致为:

  Data:存储通讯录中每个人的全部信息,名字,电话,E-mail等。

  RawContacts:存储的是个人描述信息和一些唯一确定的相关的帐号

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

  关于Data,看一下文档里面的详细内容,里面主要说了一个“数据类型”(Data kinds),对应的是Data.MIMETYPE这个列。

  Data里面也是含有对数据的“增删改查”四个基本操作。官方每个操作都提供了一些事例代码。

[java] view plain copy
  1. Cursorc=getContentResolver().query(Data.CONTENT_URI,
  2. newString[]{Data._ID,StructuredName.DISPLAY_NAME,},
  3. Data.MIMETYPE+"='"+StructuredName.CONTENT_ITEM_TYPE+"'",null,null);

这个代码就是通过联系人ID查找电话号码,电话类型,和电话标签。像里的Data._ID中的Data就是ContactsContact.Data,Phone.TYPE里面的Phone就是ContactsContract.CommonDataKinds.Phone。

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

  Data.MIMETYPE很重要,官方的文档中描述里面比较重要的几点是:

1、在Data中有一大段的公共数据段,DATA1~DATA15。

2、上面说的那些公共数据段所存的数据类型是由这个MIMETYPE决定的。

如果MIMETYPE的值是Phone.CONTENT_ITEM_TYPE,则DATA1就是电话号码,如果MIMETYPE的值是Email.CONTENT_ITEM_TYPE则DATA1的值就是E-mail地址...

  在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

  查姓名可以把StructuredName.CONTENT_ITEM_TYPE给MINETYPE就行了。


  其中游标C的结果的第二个字段(StructuredName.DISPLAY_NAME)就是姓名,准确的说应该是“显示姓名”(因为姓名也以再细分为姓和名)。

用命令行下的adb shell进入Android的模拟器,进入data/data目录下面。里面有一个com.android.providers.contacts,进入这个目录下,里面有一个databases,再进去就可以看到有个contacts2.db的文件。

  用sqlite3打开这个数据库文件

  

  查询data表里面的所有信息,可以发现里面的信息都是通讯录里面的名片。

  

  再看一下表的结构,用”.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 所对应的电话就可以了。

  代码:

[java] view plain copy
  1. /**
  2. *通过姓名(uName)来查找通讯录,返回一个list。其中"display_name"保存姓名,"phone_number"保存电话
  3. */
  4. publicList<HashMap<String,String>>getContactsByName(StringuName){
  5. List<HashMap<String,String>>list=newArrayList<HashMap<String,String>>();
  6. booleanisQueryAll=false;
  7. //cu姓名游标,cn电话号码游标
  8. Cursorcu,cn=null;
  9. //查询条件,SQL是的Where语句的后部分
  10. Stringselection=null;
  11. uName=uName.trim();
  12. //是否查询全部通讯录,如果姓名为空则是
  13. isQueryAll=uName.equals("")?true:false;
  14. if(isQueryAll){
  15. //查询全部时的,查询条件,主要用在cu游标上
  16. selection=ContactsContract.Data.MIMETYPE
  17. +"='"
  18. +ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
  19. +"'";
  20. //System.out.println("QueryForALl--"+selection);
  21. }else{
  22. //根据姓名查询时的,查询条件,主要用在cu游标上
  23. selection=ContactsContract.Data.MIMETYPE
  24. +"='"
  25. +ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
  26. +"'"
  27. +"AND"
  28. +ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
  29. +"LIKE"+"'%"+uName+"%'";
  30. //System.out.println("QueryForSome--"+selection);
  31. }
  32. try{
  33. //根据姓名查询出完整姓名和通讯录ID
  34. cu=contentReso
  35. .query(
  36. URI,
  37. newString[]{
  38. ContactsContract.Data.RAW_CONTACT_ID,
  39. ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME},
  40. selection,null,null);
  41. //根据通讯录ID,查找对应的电话号码的查询条件,主要用于cn游标
  42. selection=ContactsContract.Data.MIMETYPE+"='"
  43. +ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
  44. +"'"
  45. +"AND"
  46. +ContactsContract.Data.RAW_CONTACT_ID
  47. +"=?";
  48. //System.out.println("NumberQuery--"+selection);
  49. while(cu.moveToNext()){
  50. StringcontactId=String.valueOf(cu.getInt(0));
  51. //开始查找电话号码
  52. //System.out.println("StartQueryNum");
  53. cn=contentReso
  54. .query(
  55. URI,
  56. newString[]{ContactsContract.CommonDataKinds.Phone.NUMBER},
  57. selection,newString[]{contactId},null);
  58. while(cn.moveToNext()){
  59. //将一组通讯录记录在HashMap中
  60. HashMap<String,String>map=newHashMap<String,String>();
  61. map.put("display_name",cu.getString(1));
  62. map.put("phone_number",cn.getString(0));
  63. //将查到通讯录添加到List中
  64. list.add(map);
  65. }
  66. }
  67. //关闭游标
  68. cu.close();
  69. cn.close();
  70. }catch(Exceptione){
  71. //TODO:handleexception
  72. }
  73. returnlist;
  74. }

  最后再说一下那个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. 2011.09.26(2)——— android sample之Notepad(getSelectedItemId
  2. 创建android逐帧动画的两种方式 布局和java代码
  3. android studio的Gradle一直在sync的办法,不停的下载各种文件
  4. Android(安卓)中的各种控件
  5. Android(安卓)UI学习 - ListView
  6. 2011.09.26(2)——— android sample之Notepad(getSelectedItemId
  7. Android(安卓)换肤(三) -通过Style来完成
  8. Base64编解码Android和ios的例子,补充JNI中的例子
  9. Android(安卓)中的各种控件

随机推荐

  1. 基于Android的Linux内核的电源管理
  2. Android开发设置Activity全屏与不全屏的
  3. android app请求获取root权限
  4. Android之怎么隐藏EditText光标和自动显
  5. android机型适配终极篇
  6. Android程序入口ActivityThread和Android
  7. Android(安卓)开发环境搭建
  8. Android(安卓)绘制2D图形
  9. Android(安卓)NDK开发环境搭建及案例
  10. ActivityThread 源码笔记(1)