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,以及要访问通讯录需要的权限;
- <span style="font-family:KaiTi_GB2312;font-size:16px;"> <uses-permission android:name="android.permission.READ_CONTACTS" />
- <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
URI = content://com.android.contacts/data/emails/filter/*
URI = content://com.android.contacts/data/phone/filter/*
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
- //根据电话号码查询姓名(在一个电话打过来时,如果此电话在通讯录中,则显示姓名)
- public void testReadNameByPhone(){
- String phone = "12345678";
- //uri= content://com.android.contacts/data/phones/filter/#
- Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/"+phone);
- ContentResolver resolver = this.getContext().getContentResolver();
- Cursor cursor = resolver.query(uri, new String[]{Data.DISPLAY_NAME}, null, null, null); //从raw_contact表中返回display_name
- if(cursor.moveToFirst()){
- Log.i("Contacts", "name="+cursor.getString(0));
- }
- }
(2)查询所有的联系人
- //读取通讯录的全部的联系人
- //需要先在raw_contact表中遍历id,并根据id到data表中获取数据
- public void testReadAll(){
- //uri = content://com.android.contacts/contacts
- Uri uri = Uri.parse("content://com.android.contacts/contacts"); //访问raw_contacts表
- ContentResolver resolver = this.getContext().getContentResolver();
- Cursor cursor = resolver.query(uri, new String[]{Data._ID}, null, null, null); //获得_id属性
- while(cursor.moveToNext()){
- StringBuilder buf = new StringBuilder();
- int id = cursor.getInt(0);//获得id并且在data中寻找数据
- buf.append("id="+id);
- uri = Uri.parse("content://com.android.contacts/contacts/"+id+"/data"); //如果要获得data表中某个id对应的数据,则URI为content://com.android.contacts/contacts/#/data
- Cursor cursor2 = resolver.query(uri, new String[]{Data.DATA1,Data.MIMETYPE}, null,null, null); //data1存储各个记录的总数据,mimetype存放记录的类型,如电话、email等
- while(cursor2.moveToNext()){
- String data = cursor2.getString(cursor2.getColumnIndex("data1"));
- if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/name")){ //如果是名字
- buf.append(",name="+data);
- }
- else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/phone_v2")){ //如果是电话
- buf.append(",phone="+data);
- }
- else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/email_v2")){ //如果是email
- buf.append(",email="+data);
- }
- else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/postal-address_v2")){ //如果是地址
- buf.append(",address="+data);
- }
- else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/organization")){ //如果是组织
- buf.append(",organization="+data);
- }
- }
- String str = buf.toString();
- Log.i("Contacts", str);
- }
- }
- //一步一步添加数据
- public void testAddContacts(){
- //插入raw_contacts表,并获取_id属性
- Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
- ContentResolver resolver = this.getContext().getContentResolver();
- ContentValues values = new ContentValues();
- long contact_id = ContentUris.parseId(resolver.insert(uri, values));
- //插入data表
- uri = Uri.parse("content://com.android.contacts/data");
- //add Name
- values.put("raw_contact_id", contact_id);
- values.put(Data.MIMETYPE,"vnd.android.cursor.item/name");
- values.put("data2", "zdong");
- values.put("data1", "xzdong");
- resolver.insert(uri, values);
- values.clear();
- //add Phone
- values.put("raw_contact_id", contact_id);
- values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2");
- values.put("data2", "2"); //手机
- values.put("data1", "87654321");
- resolver.insert(uri, values);
- values.clear();
- //add email
- values.put("raw_contact_id", contact_id);
- values.put(Data.MIMETYPE,"vnd.android.cursor.item/email_v2");
- values.put("data2", "2"); //单位
- values.put("data1", "xzdong@xzdong.com");
- resolver.insert(uri, values);
- }
- public void testAddContactsInTransaction() throws Exception {
- Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
- ContentResolver resolver = this.getContext().getContentResolver();
- ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
- // 向raw_contact表添加一条记录
- //此处.withValue("account_name", null)一定要加,不然会抛NullPointerException
- ContentProviderOperation operation1 = ContentProviderOperation
- .newInsert(uri).withValue("account_name", null).build();
- operations.add(operation1);
- // 向data添加数据
- uri = Uri.parse("content://com.android.contacts/data");
- //添加姓名
- ContentProviderOperation operation2 = ContentProviderOperation
- .newInsert(uri).withValueBackReference("raw_contact_id", 0)
- //withValueBackReference的第二个参数表示引用operations[0]的操作的返回id作为此值
- .withValue("mimetype", "vnd.android.cursor.item/name")
- .withValue("data2", "xzdong").build();
- operations.add(operation2);
- //添加手机数据
- ContentProviderOperation operation3 = ContentProviderOperation
- .newInsert(uri).withValueBackReference("raw_contact_id", 0)
- .withValue("mimetype", "vnd.android.cursor.item/phone_v2")
- .withValue("data2", "2").withValue("data1", "0000000").build();
- operations.add(operation3);
- resolver.applyBatch("com.android.contacts", operations);
- }
- public void testDelete()throws Exception{
- String name = "xzdong";
- //根据姓名求id
- Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
- ContentResolver resolver = this.getContext().getContentResolver();
- Cursor cursor = resolver.query(uri, new String[]{Data._ID},"display_name=?", new String[]{name}, null);
- if(cursor.moveToFirst()){
- int id = cursor.getInt(0);
- //根据id删除data中的相应数据
- resolver.delete(uri, "display_name=?", new String[]{name});
- uri = Uri.parse("content://com.android.contacts/data");
- resolver.delete(uri, "raw_contact_id=?", new String[]{id+""});
- }
- }
核心思想:
(1)不需要更新raw_contacts,只需要更新data表;
(2)uri=content://com.android.contacts/data 表示对data表进行操作;
- public void testUpdate()throws Exception{
- int id = 1;
- String phone = "999999";
- Uri uri = Uri.parse("content://com.android.contacts/data");//对data表的所有数据操作
- ContentResolver resolver = this.getContext().getContentResolver();
- ContentValues values = new ContentValues();
- values.put("data1", phone);
- resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2",id+""})
- }
ContentProvider 增删改查通讯录的更多相关文章
- Android(java)学习笔记245:ContentProvider使用(银行数据库创建和增删改查的案例)
1. Android的四大组件: (1)Activity 用户交互的UI界面 (2)Service 后台运行的服务 (3)BroadcastReceiver 广播接收者 (4)ContentPro ...
- Android(java)学习笔记189:ContentProvider使用(银行数据库创建和增删改查的案例)
1. Android的四大组件: (1)Activity 用户交互的UI界面 (2)Service 后台运行的服务 (3)BroadcastReceiver 广播接收者 (4)ContentPro ...
- IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查
IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查 首先当然是把CNcontact包含在工程中: @import Contacts; 1.下面是增加联系人的程序段: ...
- 一、Android四大框架之ContentProvider的学习与运用,实现SQLite的增删改查。
本文系原创博客,文中不妥烦请指出,如需转载摘要请注明出处! ContentProvider的学习与运用 Alpha Dog 2016-04-13 10:27:06 首先,项目的地址:https:// ...
- JDBC+Servlet+JSP实现基本的增删改查(简易通讯录)
前言: 最近学习JavaWeb的过程中,自己实践练手了几个小项目,目前已经上传到我的Github上https://github.com/Snailclimb/JavaWebProject.目前只上传了 ...
- 【面向对象版】HashMap(增删改查)
前言: 关于什么是HashMap,HashMap可以用来做些什么,这些定义类的描述,请参照[简易版]HashMap(增删改查)的内容. 这章节主要是面向实例,直接进行HashMap(增删改查)的演示. ...
- [MongoDB]增删改查
摘要 上篇文章学习了mongodb在windows上的安装,以及如何开启mongodb,最后列举了简单的增删改查操作.本篇将继续深入学习一下增删改查. 相关文章 [MongoDB]入门操作 CRUD ...
- IOS9中联系人对象的使用及增删改查操作的函数封装
之前克服重重困难把IOS9中新的类联系人搞明白了,现在把增删改查封装成了函数,如下: // // ViewController.m // IOS9中联系人CNContact的使用 // // Crea ...
- Android-ContentProvider简单的增删改查
注意:在ContentProvider里面写对数据库增删改查的时候,千万不能 db.close(); cursor.close(); 等操作,不然其他应用访问不到数据,也没有必要写isOpen(); ...
随机推荐
- java 集合的使用 (一)
1.使用整型列表 List<int> lstInt=new List<int>(); 结果不对,报的错误是:Syntax error, insert "Dimensi ...
- js合并行
网上找了好久才找到,在这记录下. <script type="text/javascript" > function MergerRow(ID) { var tab = ...
- oracle控制文件丢失恢复
在学习群里有个同学误删除了控制文件,于是我也把自己数据库的控制文件删除了,看看能不能进行恢复,以下是整个实验的过程~~在做之前,先看看控制文件的备份方式:1.生成可以重建控制文件的脚本.2.备份二进制 ...
- c#读取快递100查询返回的JSON信息
{"message":"ok","nu":"1105016801203","companytype" ...
- 图的存储,搜索,遍历,广度优先算法和深度优先算法,最小生成树-Java实现
1)用邻接矩阵方式进行图的存储.如果一个图有n个节点,则可以用n*n的二维数组来存储图中的各个节点关系. 对上面图中各个节点分别编号,ABCDEF分别设置为012345.那么AB AC AD 关系可以 ...
- Android 日常开发总结的技术经验 60 条
1. 全部Activity可继承自BaseActivity,便于统一风格与处理公共事件,构建对话框统一构建器的建立,万一需要整体变动,一处修改到处有效. 2. 数据库表段字段常量和SQL逻辑分离,更清 ...
- django Q和F查询
Q查询——对对象的复杂查询F查询——专门取对象中某列值的操作 Q查询1.Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询,例如: from django. ...
- ubuntu 下rar解压工具安装方法
1.压缩功能安装 sudo apt-get install rar卸载 sudo apt-get remove rar2.解压功能安装 sudo apt-get install unrar卸载 sud ...
- JavaScript笔记杂谈篇(啥都有)
二维码缩放比例以43PX的倍数缩放最为标准. NuGet相关管理http://www.cnblogs.com/dudu/archive/2011/07/15/nuget.html 学习笔记: http ...
- 【T电商】 maven初识
PS:本篇博客,就是对于maven的一个简单的总结,认识.可能更多的是借鉴别人的看法,然后结合自己的使用,再加以说明. 首先,什么是maven: Apache Maven is a software ...