ContentProvider 增删改查通讯录

一、通讯录应用介绍

通讯录应用是Android自带的应用程序,我们看到此应用的时候,可能只认为这是一个应用,用数据库存储数据,但是实际上不是这样的。

通讯录是ContentProvider的应用,通讯录由两部分组成:

(1)com.android.providers.contacts的ContentProvider:真正存储数据的ContentProvider

(2)com.android.contacts:运用ContentResolver获取数据的图形用户界面;

二、获取ContactProvider的源代码

Android源代码:   http://my.oschina.net/zhanglubing/blog/40623 用Git获取;

如果要获取ContactProvider,则安装git,并打开git bash,输入

git clone https://android.googlesource.com/platform/packages/providers/ContactsProvider.git 即可;

目录结构如下:

为何要获取ContactProvider的源代码呢?

因为如果要访问ContentProvider,必须要了解URI的设置(authority,path等);只有查看源代码才能够知道;

AndroidManifest.xml为清单文件,列出了ContactProvider的authorities,以及要访问通讯录需要的权限;

[html] view plain copy

  1. <span style="font-family:KaiTi_GB2312;font-size:16px;"> <uses-permission android:name="android.permission.READ_CONTACTS" />
  2. <uses-permission android:name="android.permission.WRITE_CONTACTS" /></span>

主要的通讯录程序为ContactsProvider2.Java

authorities=contacts或com.android.contacts;

三、通讯录数据库结构介绍

表结构如下:

通讯录是存放在/data/data/com.android.providers.contacts/databases/contacts2.db,里面主要的表有:

(1)raw_contacts:存放联系人的ID,

_id属性为主键,声明为autoincrement,即不需要手动设置,其他属性也不需要手动设置就有默认值;

display_name属性为姓名;

(2)mimetypes:存放数据的类型,比如"vnd.android.cursor.item/name"表示“姓名”类型的数据,"vnd.android.cursor.item/phone_v2"表示“电话”类型的数据;

(3)data:存放具体的数据;

raw_contact_id属性用来连接raw_contacts表,每条记录表示一个具体数据;我们主要的数据(email、phone等)都存放在data表;

data1属性存放总数据;

data2属性:

-如果此记录存放姓名,则data2存放名;

-如果此记录存放电话,则data2存放类型,比如手机、家电;

-如果此记录存放组织,则data2存放类型,比如公司、其他;

-如果此记录存放地址,则data2存放类型,比如住宅,单位等;

四、编程提示

 

URI

对raw_contacts表添加、删除、更新操作:

URI =  content://com.android.contacts/raw_contacts;

对data表添加、删除、更新操作:

URI =  content://com.android.contacts/data;

根据email对data表查询

URI =     content://com.android.contacts/data/emails/filter/*

根据电话号码对data表查询

URI =     content://com.android.contacts/data/phone/filter/*

如果要根据ID查询电话,可以

URI = content://com.android.contacts/data;

然后where条件为:raw_contact_id=? and mimetype = ?

 

MIMETYPE

电话:vnd.android.cursor.item/phone_v2

姓名:vnd.android.cursor.item/name

邮件:vnd.android.cursor.item/email_v2

通信地址:vnd.android.cursor.item/postal-address_v2

组织:vnd.android.cursor.item/organization

照片:vnd.android.cursor.item/photo

Data中的常量

 

Data._ID: "_id"

Data.DISPLAY_NAME:“display_name”

Data.DATA1:“data1”

Data.DATA2:“data2”

Data.RAW_CONTACT_ID:“raw_contact_id”

Data.MIMETYPE:“mimetype”

五、对通信录做增删改查

简单的说:对通讯录操作就是对一个普通的ContentProvider操作;

1.Query

(1)根据电话号码查询姓名

[java] view plain copy

  1. //根据电话号码查询姓名(在一个电话打过来时,如果此电话在通讯录中,则显示姓名)
  2. public void testReadNameByPhone(){
  3. String phone = "12345678";
  4. //uri=  content://com.android.contacts/data/phones/filter/#
  5. Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/"+phone);
  6. ContentResolver resolver = this.getContext().getContentResolver();
  7. Cursor cursor = resolver.query(uri, new String[]{Data.DISPLAY_NAME}, null, null, null); //从raw_contact表中返回display_name
  8. if(cursor.moveToFirst()){
  9. Log.i("Contacts", "name="+cursor.getString(0));
  10. }
  11. }

(2)查询所有的联系人

[java] view plain copy

  1. //读取通讯录的全部的联系人
  2. //需要先在raw_contact表中遍历id,并根据id到data表中获取数据
  3. public void testReadAll(){
  4. //uri = content://com.android.contacts/contacts
  5. Uri uri = Uri.parse("content://com.android.contacts/contacts"); //访问raw_contacts表
  6. ContentResolver resolver = this.getContext().getContentResolver();
  7. Cursor cursor = resolver.query(uri, new String[]{Data._ID}, null, null, null);  //获得_id属性
  8. while(cursor.moveToNext()){
  9. StringBuilder buf = new StringBuilder();
  10. int id = cursor.getInt(0);//获得id并且在data中寻找数据
  11. buf.append("id="+id);
  12. uri = Uri.parse("content://com.android.contacts/contacts/"+id+"/data"); //如果要获得data表中某个id对应的数据,则URI为content://com.android.contacts/contacts/#/data
  13. Cursor cursor2 = resolver.query(uri, new String[]{Data.DATA1,Data.MIMETYPE}, null,null, null);  //data1存储各个记录的总数据,mimetype存放记录的类型,如电话、email等
  14. while(cursor2.moveToNext()){
  15. String data = cursor2.getString(cursor2.getColumnIndex("data1"));
  16. if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/name")){       //如果是名字
  17. buf.append(",name="+data);
  18. }
  19. else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/phone_v2")){  //如果是电话
  20. buf.append(",phone="+data);
  21. }
  22. else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/email_v2")){  //如果是email
  23. buf.append(",email="+data);
  24. }
  25. else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/postal-address_v2")){ //如果是地址
  26. buf.append(",address="+data);
  27. }
  28. else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/organization")){  //如果是组织
  29. buf.append(",organization="+data);
  30. }
  31. }
  32. String str = buf.toString();
  33. Log.i("Contacts", str);
  34. }
  35. }

2.Insert

(1)一步一步添加数据

注意:对某个联系人插入姓名、电话等记录时必须要插入Data.MIMETYPE(或者是"mimetype")属性,而不是插入"mimetype_id"!

比如:values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2");

[java] view plain copy

  1. //一步一步添加数据
  2. public void testAddContacts(){
  3. //插入raw_contacts表,并获取_id属性
  4. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  5. ContentResolver resolver = this.getContext().getContentResolver();
  6. ContentValues values = new ContentValues();
  7. long contact_id = ContentUris.parseId(resolver.insert(uri, values));
  8. //插入data表
  9. uri = Uri.parse("content://com.android.contacts/data");
  10. //add Name
  11. values.put("raw_contact_id", contact_id);
  12. values.put(Data.MIMETYPE,"vnd.android.cursor.item/name");
  13. values.put("data2", "zdong");
  14. values.put("data1", "xzdong");
  15. resolver.insert(uri, values);
  16. values.clear();
  17. //add Phone
  18. values.put("raw_contact_id", contact_id);
  19. values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2");
  20. values.put("data2", "2");   //手机
  21. values.put("data1", "87654321");
  22. resolver.insert(uri, values);
  23. values.clear();
  24. //add email
  25. values.put("raw_contact_id", contact_id);
  26. values.put(Data.MIMETYPE,"vnd.android.cursor.item/email_v2");
  27. values.put("data2", "2");   //单位
  28. values.put("data1", "[email protected]");
  29. resolver.insert(uri, values);
  30. }

(2)批量添加数据

核心代码:

(1)ContentProviderOperation operation = ContentProviderOperation.newInsert(uri).withValue("key","value").build();

(2)resolver.applyBatch("authorities",operations);//批量提交

[java] view plain copy

  1. public void testAddContactsInTransaction() throws Exception {
  2. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  3. ContentResolver resolver = this.getContext().getContentResolver();
  4. ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
  5. // 向raw_contact表添加一条记录
  6. //此处.withValue("account_name", null)一定要加,不然会抛NullPointerException
  7. ContentProviderOperation operation1 = ContentProviderOperation
  8. .newInsert(uri).withValue("account_name", null).build();
  9. operations.add(operation1);
  10. // 向data添加数据
  11. uri = Uri.parse("content://com.android.contacts/data");
  12. //添加姓名
  13. ContentProviderOperation operation2 = ContentProviderOperation
  14. .newInsert(uri).withValueBackReference("raw_contact_id", 0)
  15. //withValueBackReference的第二个参数表示引用operations[0]的操作的返回id作为此值
  16. .withValue("mimetype", "vnd.android.cursor.item/name")
  17. .withValue("data2", "xzdong").build();
  18. operations.add(operation2);
  19. //添加手机数据
  20. ContentProviderOperation operation3 = ContentProviderOperation
  21. .newInsert(uri).withValueBackReference("raw_contact_id", 0)
  22. .withValue("mimetype", "vnd.android.cursor.item/phone_v2")
  23. .withValue("data2", "2").withValue("data1", "0000000").build();
  24. operations.add(operation3);
  25. resolver.applyBatch("com.android.contacts", operations);
  26. }

3.Delete

核心思想:

(1)先在raw_contacts表根据姓名(此处的姓名为name记录的data2的数据而不是data1的数据)查出id;

(2)在data表中只要raw_contact_id匹配的都删除;

[java] view plain copy

  1. public void testDelete()throws Exception{
  2. String name = "xzdong";
  3. //根据姓名求id
  4. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  5. ContentResolver resolver = this.getContext().getContentResolver();
  6. Cursor cursor = resolver.query(uri, new String[]{Data._ID},"display_name=?", new String[]{name}, null);
  7. if(cursor.moveToFirst()){
  8. int id = cursor.getInt(0);
  9. //根据id删除data中的相应数据
  10. resolver.delete(uri, "display_name=?", new String[]{name});
  11. uri = Uri.parse("content://com.android.contacts/data");
  12. resolver.delete(uri, "raw_contact_id=?", new String[]{id+""});
  13. }
  14. }

4.Update

核心思想:

(1)不需要更新raw_contacts,只需要更新data表;

(2)uri=content://com.android.contacts/data 表示对data表进行操作;

[java] view plain copy

    1. public void testUpdate()throws Exception{
    2. int id = 1;
    3. String phone = "999999";
    4. Uri uri = Uri.parse("content://com.android.contacts/data");//对data表的所有数据操作
    5. ContentResolver resolver = this.getContext().getContentResolver();
    6. ContentValues values = new ContentValues();
    7. values.put("data1", phone);
    8. resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2",id+""})
    9. }
时间: 2024-10-16 16:59:36

ContentProvider 增删改查通讯录的相关文章

【contentprovider系列5】综述使用contentprovider增删改查联系人数据

增加:一般操作的是data表. 查找:一般涉及的是多表的查询. 修改:也是修改的data表中的数据. 删除:涉及多表的查询,最后还是删除的data表中的数据. 综上,所有实际的数据都是存放在data表中的.raw_contacts表和data表是一对多的关系,而contacts表一行是多行row_contacts表的综合,因为可能设计多个账户.具体的示意图见如下:

对联系人进行增删改查

我已经将联系人操作的方法进行了封装,暴露了几个重要的方法,方便以后调用. 1. public void printContactsList() // 获取到的联系人列表(用于测试用) 2. public ArrayList<ContactBean> getContactsList() // 得到手机和SIM卡中的联系人列表(姓名 + 电话号码) 3. public void add(String name, String phoneNumber) // 添加一个新的联系人数据 4. publi

IOS开发中使用CNContact对通讯录增删改查

IOS开发中使用CNContact对通讯录增删改查 首先当然是把CNcontact包含在工程中: 1 @import Contacts; 1.下面是增加联系人的程序段: 1 CNMutableContact * contact = [[CNMutableContact alloc]init]; 2 contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"22"]); 3 //设置名字 4 contact.gi

Android(java)学习笔记245:ContentProvider之银行数据库创建和增删改查的实现

1.Android的四大组件: (1)Activity  用户交互的UI界面 (2)Service  后台运行的服务 (3)BroadcastReceiver 广播接收者 (4)ContentProvider  内容提供者 2. ContentProvider  内容提供者 用途:把应用程序私有的数据暴露给别的应用程序. 3.下面通过一个银行数据库创建和增删改查的实现案例说明ContentProvider的使用: (1)首先我们这里要用到数据库,首先我们必须先扩展一个抽象类SQLiteOpenH

Android中内容提供者ContentProvider实现数据库增删改查

1.我们首先new一个我们自己的类集成ContentProvider,并实现方法如下 package com.wzw.sqllitedemo.providers; import com.wzw.sqllitedemo.db.PersonSQLiteOpenHelper; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues;

Android通讯录数据库介绍与基本操作(增删改查)

Android通讯录数据库介绍与基本操作(增删改查) 2014年2月21日 Android通讯录管理总结 这几天导师安排我一个任务就是研究一下Android通讯录获取联系人.通话记录.短信的方法,还有看看不同Android版本之间的异同是否能做到兼容之类的事情.Android通讯录这一块,我个人感觉是挺乱的,网上一堆关于查询本地数据库获取联系人的方法,但似乎都没有仔细说明数据有哪些重要的表,它们之间有什么联系.下面是本人查询资料总结的一下知识点,方便童鞋们以后用到. http://xys2891

【C】利用单链表数据结构实现通讯录,链表的增删改查

C语言中实现链表,是需要利用到C语言中比较难的结构体与指针才能实现. 结构体中放一个指向后接节点的指针与每一个结点应该存放的信息. 下面做一个命令行的通讯录来说明链表的增删改查这个问题. 一开始让用户输入链表,按1可以输出,按3可以删除. 可以修改: 可以插入. 按0则可以退出: 代码如下: #include<stdio.h> #include<stdlib.h> typedef struct Linklist{ char name[10];//存放名字 char num[10];

【黑马Android】(04)数据库的创建和sql语句增删改查/LinearLayout展示列表数据/ListView的使用和BaseAdater/内容提供者创建

数据库的创建和sql语句增删改查 1. 加载驱动. 2. 连接数据库. 3. 操作数据库. 创建表: create table person( _id integer primary key, name varchar(20), age integer ); 添加: insert into person(name, age) values('lisi', 19); 删除: delete from person where _id = 1; 修改: update person set name =

IOS9中联系人对象的使用及增删改查操作的函数封装

之前克服重重困难把IOS9中新的类联系人搞明白了,现在把增删改查封装成了函数,如下: 1 // 2 // ViewController.m 3 // IOS9中联系人CNContact的使用 4 // 5 // Created by mac on 16/5/6. 6 // Copyright © 2016年 mzw. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 //导入IOS9联系人模型 12 @impo