黎活明8天快速掌握android视频教程--22_访问通信录中的联系人和添加联系人
Android系统中联系人的通讯录的contentProvide是一个单独的apk,显示在界面的contact也是一个独立的apk,联系人apk通过contentProvide访问底层的数据库。
现在我们自己建立一个apk,访问底层数据库中的联系人
常用的几张表如下
表raw_contacts:存放联系人的ID
字段display_name:存放姓+名的组合,便于快速得到用户的姓名。注意,当向该表添加联系人时该字段是为null的,只有在向data表中添加姓名时,才会发出update语句来更新该字段。
首先,我们可以在File Explorer视图下找到contacts2.db文件,这是通讯录的文件
然后,我们用SQLite打开,分析下它的数据库结构:
raw_contacts表:
表raw_contacts:存放联系人的ID
字段display_name:存放姓+名的组合,便于快速得到用户的姓名。注意,当向该表添加联系人时该字段是为null的,只有在向data表中添加姓名时,才会发出update语句来更新该字段。
raw_contacts表中的_id和data表中的_id是一一对应的关系
表data:存放联系人的详细信息,如姓名、手机等,主要几个字段的含义如下:
字段data1:存放具体数据
字段data2:对于电话号码,存放类型:家庭电话、手机号等,2代表手机号
对于邮箱,存放类型
对于姓名,存放名字部分,data3存放姓氏部分
字段mimetype_id:区分数据的类型,5-电话数据,6-姓名数据,1-email数据,对应表mimetypes中的记录ID
mimetypes表:
操作数据库的时候需要添加权限:
使用ContentResolver对通信录中的数据进行添加、删除、修改和查询操作,需要加入读写联系人信息的权限
<uses-permissionandroid:name="android.permission.READ_CONTACTS" />
<uses-permissionandroid:name="android.permission.WRITE_CONTACTS" />
我们来看下面的代码读取联系人的信息:
package com.example.test; import java.util.ArrayList; import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log; public class ContactsTest extends AndroidTestCase {
private static final String TAG = "ContactsTest"; /**
* 获取联系人
* */
public void testGetContacts(){
Uri uri = Uri.parse("content://com.android.contacts/contacts"); // 访问所有联系人
ContentResolver resolver = getContext().getContentResolver();
Cursor cursor = resolver.query(uri, new String[]{"_id"}, null, null, null);
while(cursor.moveToNext()){
int contactsId = cursor.getInt(0);
StringBuilder sb = new StringBuilder("contactsId=");
sb.append(contactsId);
uri = Uri.parse("content://com.android.contacts/contacts/" + contactsId + "/data"); //某个联系人下面的所有数据
Cursor dataCursor = resolver.query(uri, new String[]{"mimetype", "data1", "data2"}, null, null, null);
while(dataCursor.moveToNext()){
String data = dataCursor.getString(dataCursor.getColumnIndex("data1"));
String type = dataCursor.getString(dataCursor.getColumnIndex("mimetype"));
if("vnd.android.cursor.item/name".equals(type)){ // 如果他的mimetype类型是name
sb.append(", name=" + data);
} else if("vnd.android.cursor.item/email_v2".equals(type)){ // 如果他的mimetype类型是email
sb.append(", email=" + data);
} else if("vnd.android.cursor.item/phone_v2".equals(type)){ // 如果他的mimetype类型是phone
sb.append(", phone=" + data);
}
}
Log.i(TAG, sb.toString());
}
} /**
* 根据来电号码获取联系人名字
* */
public void testGetContactsByNumber(){
String number = "15292328801";
Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);
ContentResolver resolver = getContext().getContentResolver();
Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);
if(cursor.moveToFirst()){
String name = cursor.getString(0);
Log.i(TAG, name);
}
} /**
* 添加联系人
* 数据一个表一个表的添加,每次都调用insert方法
* */
public void testAddContacts(){
/* 往 raw_contacts 中添加数据,并获取添加的id号*/
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
ContentResolver resolver = getContext().getContentResolver();
ContentValues values = new ContentValues();
long contactId = ContentUris.parseId(resolver.insert(uri, values)); /* 往 data 中添加数据(要根据前面获取的id号) */
// 添加姓名
uri = Uri.parse("content://com.android.contacts/data");
values.put("raw_contact_id", contactId);
values.put("mimetype", "vnd.android.cursor.item/name");
values.put("data2", "周国平");
resolver.insert(uri, values); // 添加电话
values.clear();
values.put("raw_contact_id", contactId);
values.put("mimetype", "vnd.android.cursor.item/phone_v2");
values.put("data2", "2");
values.put("data1", "15099144117");
resolver.insert(uri, values); // 添加Email
values.clear();
values.put("raw_contact_id", contactId);
values.put("mimetype", "vnd.android.cursor.item/email_v2");
values.put("data2", "2");
values.put("data1", "zhouguoping@qq.com");
resolver.insert(uri, values);
} /**
* 添加联系人
* 在同一个事务中完成联系人各项数据的添加
* 使用ArrayList<ContentProviderOperation>,把每步操作放在它的对象中执行
* */
public void testAddContacts2(){
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
ContentResolver resolver = getContext().getContentResolver();
// 第一个参数:内容提供者的主机名
// 第二个参数:要执行的操作
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); // 操作1.添加Google账号,这里值为null,表示不添加
ContentProviderOperation operation = ContentProviderOperation.newInsert(uri)
.withValue("account_name", null)// account_name:Google账号
.build(); // 操作2.添加data表中name字段
uri = Uri.parse("content://com.android.contacts/data");
ContentProviderOperation operation2 = ContentProviderOperation.newInsert(uri)
// 第二个参数int previousResult:表示上一个操作的位于operations的第0个索引,
// 所以能够将上一个操作返回的raw_contact_id作为该方法的参数
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/name")
.withValue("data2", "周国平")
.build(); // 操作3.添加data表中phone字段
uri = Uri.parse("content://com.android.contacts/data");
ContentProviderOperation operation3 = ContentProviderOperation.newInsert(uri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/phone_v2")
.withValue("data2", "2")
.withValue("data1", "15099144117")
.build(); // 操作4.添加data表中的Email字段
uri = Uri.parse("content://com.android.contacts/data");
ContentProviderOperation operation4 = ContentProviderOperation
.newInsert(uri).withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/email_v2")
.withValue("data2", "2")
.withValue("data1", "zhouguoping@qq.com").build(); operations.add(operation);
operations.add(operation2);
operations.add(operation3);
operations.add(operation4); try {
resolver.applyBatch("com.android.contacts", operations);
} catch (Exception e) {
e.printStackTrace();
}
}
}
黎活明8天快速掌握android视频教程--22_访问通信录中的联系人和添加联系人的更多相关文章
- 黎活明8天快速掌握android视频教程--21_监听ContentProvider中数据的变化
采用ContentProvider除了可以让其他应用访问当前的app的数据之外,还有可以实现当app的数据发送变化的时候,通知注册了数据变化通知的调用者 其他所有的代码都和第20讲的一样,不同的地方看 ...
- 黎活明8天快速掌握android视频教程--20_采用ContentProvider对外共享数据
1.内容提供者是让当前的app的数据可以让其他应用访问,其他应该可以通过内容提供者访问当前app的数据库 contentProvider的主要目的是提供一个开发的接口,让其他的应该能够访问当前应用的数 ...
- 黎活明8天快速掌握android视频教程--15_采用Pull解析器解析和生成XML内容
1.该项目主要有下面的两个作用 (1)将xml文件解析成对象的List对象,xml文件可以来自手机本地,也可以来自服务器返回的xml数据 (2)强list对象保存成xml文件,xml保存到手机的内存卡 ...
- 黎活明8天快速掌握android视频教程--25_网络通信之资讯客户端
1 该项目的主要功能是:后台通过xml或者json格式返回后台的视频资讯,然后Android客户端界面显示出来 首先后台新建立一个java web后台 采用mvc的框架 所以的servlet都放在se ...
- 黎活明8天快速掌握android视频教程--24_网络通信之网页源码查看器
1 该项目的主要功能就是从将后台的html网页在Android的界面上显示出来 后台就是建立一个java web工程在工程尚建立一个html或者jsp文件就可以了,这里主要看Android客户端的程序 ...
- 黎活明8天快速掌握android视频教程--23_网络通信之网络图片查看器
1.首先新建立一个java web项目的工程.使用的是myeclipe开发软件 图片的下载路径是http://192.168.1.103:8080/lihuoming_23/3.png 当前手机和电脑 ...
- 黎活明8天快速掌握android视频教程--19_采用ListView实现数据列表显示
1.首先整个程序也是采用mvc的框架 DbOpenHelper 类 package dB; import android.content.Context; import android.databas ...
- 黎活明8天快速掌握android视频教程--17_创建数据库与完成数据添删改查
1.我们首先来看下整个项目 项目也是采用mvc的框架 package dB; import android.content.Context; import android.database.sqlit ...
- 黎活明8天快速掌握android视频教程--16_采用SharedPreferences保存用户偏好设置参数
SharedPreferences保存的数据是xml格式,也是存在数据保存的下面四种权限: 我们来看看 我们来看看具体的业务操作类: /** * 文件名:SharedPrecences.java * ...
随机推荐
- [批处理教程之Git]001.Git 常用命令大全
基本技巧 1.安装后的第一步 安装git后,第一件事你需要设置你的名字和邮箱,因为每次提交都需要这些信息. $ git config --global user.name "Some One ...
- [工具推荐]005.Axure RP Pro 7.0模拟C#TAB控件
有一次,主管安排我写一个项目的原型,但是项目中涉及到了Tab控件,在Axure中的控件中找了一番,没有找着Tab控件.那么我们只能换种法子来实现它了,我们用到了Dynamic Panel来模拟. 1. ...
- 使用fileupload组件
1. 进行文件上传时, 表单需要做的准备: 1). 请求方式为 POST: <form action="uploadServlet" method="post&qu ...
- python常见面试题讲解(八)提取不重复的整数
题目描述 输入一个int型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数. 输入描述: 输入一个int型整数 输出描述: 按照从右向左的阅读顺序,返回一个不含重复数字的新的整数 示例1 ...
- css 3 背景图片为渐变色(渐变色背景图片) 学习笔记
6年不研究CSS发现很多现功能都没有用过,例如渐变色,弹性盒子等,年前做过一个简单的管理系统,由于本人美工不好,设计不出好看的背景图片,偶然百度到背景图片可以使用渐变色(感觉发现了新大陆).以后的项目 ...
- Java实现蓝桥杯VIP算法训练 数组逆序排列
试题 算法训练 数组逆序排列 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 编写一个程序,读入一组整数(不超过20个),并把它们保存在一个整型数组中.当用户输入0时,表示输入结束. ...
- Java实现 蓝桥杯VIP 算法提高 插入排序
算法提高 插入排序 时间限制:1.0s 内存限制:256.0MB 插入排序 问题描述 排序,顾名思义,是将若干个元素按其大小关系排出一个顺序.形式化描述如下:有n个元素a[1],a[2],-,a[ ...
- Java实现 LeetCode 110 平衡二叉树
110. 平衡二叉树 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1. 示例 1: 给定二叉树 [3,9 ...
- Java实现字符串转换成整数
1 问题描述 输入一个由数字组成的字符串,请把它转换成整数并输出.例如,输入字符串"123",输出整数123. 请写出一个函数实现该功能,不能使用库函数. 2 解决方案 解答本问题 ...
- Redis集群方式
Redis有三种集群方式:主从复制,哨兵模式和集群. 1.主从复制 主从复制原理: 从服务器连接主服务器,发送SYNC命令: 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用 ...