【转】Android 增,删,改,查 通讯录中的联系人
一.权限
操作通讯录必须在AndroidManifest.xml中先添加2个权限,
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>
二.通讯录数据库表介绍 (重点)
1.minetypes表

2.data表

3.raw_contacts表


注意: 3表第二个图是接第一图的右边的,因为大小的原因,截成了2张图。
首先说一下,联系人的信息操作前,必须把数据库的这3个表仔细看一下,看不懂也没关系,等会对进行增删改查的操作的时候,再回来对照数据库,这样你能够更加方便理解和记忆代码。否则,死记代码,过两天就忘的一干二净。
通讯录是存放在/data/data/com.android.providers.contacts/databases/contacts2.db,里面主要的表有:
(1)raw_contacts:存放联系人的 ID,_id属性为主键,声明为autoincrement,即不需要手动设置,其他属性也不需要手动设置就有默认值;display_name属性为姓名;sort_key属性可以用于查询后的排序
(2)mimetypes:存放数据的类型,比如"vnd.android.cursor.item/name"表示“姓名”类型的数据,"vnd.android.cursor.item/phone_v2"表示“电话”类型的数据;
(3)data:存放具体的数据;raw_contact_id 属性用来连接raw_contacts表,每条记录表示一个具体数据;raw_contact_id 需要重点记住,手机中显示的每一个联系人对应一个固定的raw_contact_id,raw_contact_id对应着 raw_contacts表的 _id ,他俩是相同的值,两个表之间的关系必须理清。(我刚开始就是没有理清表之间的关系,以及各个字段代表的意思,做起来就感觉很混乱,这3个表很重要)我们主要的数据(email、phone等)都存放在data表;
data1属性存放总数据;
data2属性:
-如果此记录存放姓名,则data2存放名;
-如果此记录存放电话,则data2存放类型,比如手机、家电;
-如果此记录存放组织,则data2存放类型,比如公司、其他;
-如果此记录存放地址,则data2存放类型,比如住宅,单位等
三.重要数据
URI
对raw_contacts表添加、删除、更新操作:
URI = content://com.android.contacts/raw_contacts;
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
URI =content://com.android.contacts/data/emails/filter/*
URI =content://com.android.contacts/data/phone/filter/*
然后where条件为:raw_contact_id=? and mimetype = ?
MIMETYPE
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”
四.增删改查的实现
1.query
(1)查询所有的联系人

//读取通讯录的全部的联系人
//需要先在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();
//获得_id属性
Cursor cursor = resolver.query(uri, new String[]{Data._ID}, null, null, null);
while(cursor.moveToNext()){
StringBuilder buf = new StringBuilder();
//获得id并且在data中寻找数据
int id = cursor.getInt(0);
buf.append("id="+id);
uri = Uri.parse("content://com.android.contacts/contacts/"+id+"/data");
//data1存储各个记录的总数据,mimetype存放记录的类型,如电话、email等
Cursor cursor2 = resolver.query(uri, new String[]{Data.DATA1,Data.MIMETYPE}, null,null, null);
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);
}
}

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

//根据电话号码查询姓名(在一个电话打过来时,如果此电话在通讯录中,则显示姓名)
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.Insert
注意:对某个联系人插入姓名、电话等记录时必须要插入Data.MIMETYPE(或者是"mimetype")属性,而不是插入"mimetype_id"!
比如:values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2")

//一步一步添加数据
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);
}

批量添加数据
核心代码:
(1)ContentProviderOperation operation = ContentProviderOperation.newInsert(uri).withValue("key","value").build();
(2)resolver.applyBatch("authorities",operations);//批量提交

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+""})
}

转发自:http://lichangsong.blog.51cto.com/7997447/1306033
from:https://www.cnblogs.com/liaojie970/p/5744580.html
【转】Android 增,删,改,查 通讯录中的联系人的更多相关文章
- Android 增,删,改,查 通讯录中的联系人
一.权限 操作通讯录必须在AndroidManifest.xml中先添加2个权限, <uses-permission android:name="android.permission. ...
- 好用的SQL TVP~~独家赠送[增-删-改-查]的例子
以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...
- iOS FMDB的使用(增,删,改,查,sqlite存取图片)
iOS FMDB的使用(增,删,改,查,sqlite存取图片) 在上一篇博客我对sqlite的基本使用进行了详细介绍... 但是在实际开发中原生使用的频率是很少的... 这篇博客我将会较全面的介绍FM ...
- iOS sqlite3 的基本使用(增 删 改 查)
iOS sqlite3 的基本使用(增 删 改 查) 这篇博客不会讲述太多sql语言,目的重在实现sqlite3的一些基本操作. 例:增 删 改 查 如果想了解更多的sql语言可以利用强大的互联网. ...
- 第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据
第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据 ADO.NET 为什么要学习? 我们要搭建一个平台(Web/Winform ...
- django ajax增 删 改 查
具于django ajax实现增 删 改 查功能 代码示例: 代码: urls.py from django.conf.urls import url from django.contrib impo ...
- ADO.NET 增 删 改 查
ADO.NET:(数据访问技术)就是将C#和MSSQL连接起来的一个纽带 可以通过ADO.NET将内存中的临时数据写入到数据库中 也可以将数据库中的数据提取到内存中供程序调用 ADO.NET所有数据访 ...
- MVC EF 增 删 改 查
using System;using System.Collections.Generic;using System.Linq;using System.Web;//using System.Data ...
- python基础中的四大天王-增-删-改-查
列表-list-[] 输入内存储存容器 发生改变通常直接变化,让我们看看下面列子 增---默认在最后添加 #append()--括号中可以是数字,可以是字符串,可以是元祖,可以是集合,可以是字典 #l ...
随机推荐
- C++中 引用&与取地址&的区别
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- Chapter 4 Invitations——26
"I wanted to ask you something, but you sidetracked me," he chuckled. He seemed to have re ...
- leetcode — unique-binary-search-trees-ii
``` import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util ...
- leetcode — partition-list
/** * Source : https://oj.leetcode.com/problems/partition-list/ * * * Given a linked list and a valu ...
- 在.NET Core中使用简单的插件化机制
前言 插件化,其实也并不是什么新东西了,像nopCommerce等开源项目都有类似的机制,而且功能比较完善和齐全. 相信大家都对接过不少支付方式,支付宝.微信以及各大银行或第三方的支付公司. 我们可以 ...
- kubernetes学习01—kubernetes介绍
本文收录在容器技术学习系列文章总目录 一.简介 1.Kubernetes代码托管在GitHub上:https://github.com/kubernetes/kubernetes/. 2.Kubern ...
- Connection 对象简介 方法解读 JDBC简介(四)
通过驱动管理器DriverManager的getConnection方法,可以创建到指定URL的连接 Connection conn = DriverManager.getConnection ...
- [一]FileDescriptor文件描述符 标准输入输出错误 文件描述符
文件描述符 当应用程序请求打开或者操作文件时,操作系统为应用程序设置一张文件列表,具体的实现形式此处不深入说明 操作系统会提供给你一个非负整数,作为一个索引号,它的作用就像地址或者说指针或者说偏移 ...
- 【Node.js】通过mongoose得到模型,不能新添字段的问题
问题描述 通过node.js为查询到的json对象添加新的字段,对象成功保存到数据库中,但新增字段却没保存. 前几天用vue+node.js+mongodb技术做一个购物车功能的网页,发现node.j ...
- docker 创建mysql镜像,并成功进行远程连接
1.安装 1.1 拉取镜像 docker pull mysql 拉取成功可以验证一下 docker images 1.2 创建并启动一个mysql容器 docker run --name ly-mys ...