Android手机通讯录解析

相关图片上传麻烦,原文件到我的博客上传的文件里下载。

1、通讯录应用介绍

通讯录应用是Android自带的应用程序,我们看到此应用的时候,可能只认为这是一个应用,用数据库存储数据,但是实际上不是这样的。
通讯录是ContentProvider的应用,通讯录由两部分组成:
(1)com.android.providers.contacts的ContentProvider:真正存储数据的ContentProvider
(2)com.android.contacts:运用ContentResolver获取数据的图形用户界面;

2、通讯录数据库目录结构

(1)、通讯录数据库目录结构的获取

打开Eclipse软件,调出虚拟机。如果已经创建过虚拟机,则只需要运行程序,如下图

如果没有创建就需要再去创建一个虚拟机。

调出虚拟机效果如下:

接下来就要:

通讯录是存放在/data/data/com.android.providers.contacts/databases/contacts2.db里的

接下来就是导出联系人的数据库:

导出后得到这样的数据库:

这个是QLite Database
Browser 工具

打开它把contacts2.db数据库拖进去就可以了。

得到如下:

查看数据库表中数据:

到此如何获取手机数据到此结束,前期工作完成。

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

这是手机通讯录直接相关联的几张表,圈出来的比较重要。

(1)       
mimetype表

(2)       
contacts表

此处的name_raw_contact_id为raw_contacts表的主键

(3)       
raw_contacts表

此处_id为raw_contacts表的主键,version翻译后叫版本号,一般一个联系人创建后版本号就从2开始,当这个联系人每做一次操作后version都增加,一般是增加1,但有时不确定反正他会增加。对于Android手机而言,它本身自带了一个通讯录,他对与联系人的删除操作就用户而言是删除了,因为在用户界面没有了该来联系人了。但是事实上Android并没有真正删除它。仅仅是在raw_contacts表中把deleted字段标记为了1,意思是说“1”代表删除了,“0”代表联系人没删除,是存在的。contact_id来自contacts表的主键。这样contacts和raw_contacts联系在一起了。

(4)       
data表

data表中的mimetype_id来自mimetype表,raw_contact_id来自raw_contacts表。一般来说data1到data15的字段都是存放数据的。

其中mimetype_id=5代表电话号码mimetype_id=7代表姓名。当mimetype_id=5时data1存放电话号码,data2存放电话号码的类型,data2=2,代表电话号码为手机号。

2、3、手机通讯录的操作介绍

(1)新增  
这里介绍了两种方法

/**

* 将一组联系人添加到手机通讯录中

*

* @param Contacts

* @param context

*/

public static void AddContact(ContactInfo[] Contacts, Context context) {

for (int i = 0; i < Contacts.length; i++) {

ContentValues values = new ContentValues();

// 下面的操作会根据RawContacts表中已有的rawContactId使用情况自动生成新联系人的rawContactId

Uri
rawContactUri = context.getContentResolver().insert(

RawContacts.CONTENT_URI, values);

long rawContactId = ContentUris.parseId(rawContactUri);

// 向data表插入姓名数据

if (Contacts[i].Name != "") {

values.clear();

values.put(Data.RAW_CONTACT_ID, rawContactId);

values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

values.put(StructuredName.GIVEN_NAME, Contacts[i].Name);

context.getContentResolver().insert(

ContactsContract.Data.CONTENT_URI, values);

}

// 向data表插入电话数据

if (Contacts[i].Num != "") {

values.clear();

values.put(Data.RAW_CONTACT_ID, rawContactId);

values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

values.put(Phone.NUMBER, Contacts[i].Num);

values.put(Phone.TYPE, Phone.TYPE_MOBILE);

context.getContentResolver().insert(

ContactsContract.Data.CONTENT_URI, values);

}

}

}

/**

* 将单个联系人添加到通讯录中

*

* @param Contact

* @param context

*/

public static void AddContact(ContactInfo Contact, Context context) {

ContentValues values = new ContentValues();

// 下面的操作会根据RawContacts表中已有的rawContactId使用情况自动生成新联系人的rawContactId

Uri rawContactUri =
context.getContentResolver().insert(

RawContacts.CONTENT_URI, values);

long rawContactId = ContentUris.parseId(rawContactUri);

// 向data表插入姓名数据

if (Contact.Name != "") {

values.clear();

values.put(Data.RAW_CONTACT_ID, rawContactId);

values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

values.put(StructuredName.GIVEN_NAME, Contact.Name);

context.getContentResolver().insert(

ContactsContract.Data.CONTENT_URI, values);

}

// 向data表插入电话数据

if (Contact.Num != "") {

values.clear();

values.put(Data.RAW_CONTACT_ID, rawContactId);

values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

values.put(Phone.NUMBER, Contact.Num);

values.put(Phone.TYPE, Phone.TYPE_MOBILE);

context.getContentResolver().insert(

ContactsContract.Data.CONTENT_URI, values);

}

}

public static void testAddContacts(ContactInfo[] Contacts,
Context context){

for (int i = 0; i < Contacts.length; i++) {

//插入raw_contacts表,并获取_id属性

Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); //获取操作的表的路径

ContentResolver resolver = context.getContentResolver(); //类似.NET中的上下文对象或数据库操作

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", Contacts[i].Name);

values.put("data1", Contacts[i].Name);

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", Contacts[i].Num);

resolver.insert(uri, values);

values.clear();

}

}

public static void testAddContacts(ContactInfo Contact, Context
context){

//插入raw_contacts表,并获取_id属性

Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");

ContentResolver resolver = context.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", Contact.Name);

values.put("data1", Contact.Name);

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", Contact.Num);

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", "www.2cto.com");

resolver.insert(uri, values); */

}

(2)修改  此处也介绍两种方法针对ID的来源

/**

* 更新联系人

*

* @param context

*           
上下文对象

* @param name

*       
    联系人姓名

* @param number

*           
手机号

* @param ContactId

*           
ID(此ID是由通讯录数据库自动生成的,并且该ID为contacts表中的主键)

*/

public static void testUpdate(Context context, String name,

String number, String
ContactId){

String version="0";

String rawContactsId ="";

ContentResolver cr = context.getContentResolver();

//依contacts表中的主键查找raw_contacts表中的ID即主键

Cursor rawContactsIdCur = cr.query(RawContacts.CONTENT_URI,

null, RawContacts.CONTACT_ID + " = ?",

new String[] { ContactId }, null);

if (rawContactsIdCur.moveToFirst()) {

version = rawContactsIdCur.getString(rawContactsIdCur

.getColumnIndex(RawContacts.VERSION));

//获得raw_contacts表中的主键

rawContactsId = rawContactsIdCur.getString(rawContactsIdCur

.getColumnIndex(RawContacts._ID));

}

ContentResolver resolver = context.getContentResolver();

ContentValues values = new
ContentValues();

Uri uri = Uri.parse("content://com.android.contacts/data");//对data表的所有数据操作

resolver = context.getContentResolver();

values.clear();

values = new ContentValues();

values.put("data1", number);

//依raw_contacts表中的ID对data表做相应的修改

resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2",rawContactsId}) ;

values.clear();

values.put("data2", name);

values.put("data1", name);

resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/name",rawContactsId}) ;

rawContactsIdCur.close();

}

/**

*
更新联系人

*

*
@param context

*           
上下文对象

*
@param name

*           
联系人姓名

*
@param number

*           
手机号

*
@param ContactId

*           
ID(此ID是由通讯录数据库自动生成的,并且该ID为raw_contacts表中的主键)

*/

public static void updateContact(Context context, String name,

String number, String ContactId)

{

ContentValues values = new ContentValues();

// 更新姓名

values.clear();

values.put(StructuredName.GIVEN_NAME, name);

context.getContentResolver().update(ContactsContract.Data.CONTENT_URI,

values,

Data.RAW_CONTACT_ID + "=? and " + Data.MIMETYPE + "=?",

new String[] { ContactId, StructuredName.CONTENT_ITEM_TYPE });

// 更新电话

values.clear();

values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, number);

context.getContentResolver().update(ContactsContract.Data.CONTENT_URI,

values,

Data.RAW_CONTACT_ID + "=? and " + Data.MIMETYPE + "=?",

new String[] { ContactId, Phone.CONTENT_ITEM_TYPE });

}

(3)删除

这里是彻底删除,把data,contacts,raw_contacts 表中的数据以并删除,而Android自带的手机通讯录删除操作不是真正意义上的删除,仅仅是将raw_contacts表中的deleted字段改为了“1”。

/**

* 删除联系人

*

* @param context

*           
上下文对象

* @param ContactId

*           
联系人ID

*           
ID(此ID是请求数据传递过来的,并且该ID为raw_contacts表中的主键)

*/

public static void DeleteContact(Context context, String ContactId)

{

Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");

ContentResolver resolver = context.getContentResolver();

Cursor cursor = resolver.query(uri, new String[]{RawContacts._ID},"contact_id=?", new String[]{ContactId}, null);

if(cursor.moveToFirst()){

int id = cursor.getInt(0);

//根据id删除data中的相应数据

resolver.delete(uri, "_id=?", new String[]{id+""});

uri = Uri.parse("content://com.android.contacts/data");

resolver.delete(uri, "raw_contact_id=?", new String[]{id+""});

}

}

(4)读取联系人

/**

* 获取联系人

*

* @return list数组,包含手机通讯录中的联系人

*/

private List<Map<String, Object>> getContacts() {

List<Map<String, Object>>
list = new ArrayList<Map<String,
Object>>();

// 获取用来操作数据的类的对象,对联系人的基本操作都是使用这个对象

ContentResolver cr =
getContentResolver();

// 查询contacts表的所有记录

Cursor cur =
cr.query(ContactsContract.Contacts.CONTENT_URI, null,

null, null, null);

String deleted = "1";

String version = "0";

// 如果记录不为空

if (cur.getCount() > 0) {

// 游标初始指向查询结果的第一条记录的上方,执行moveToNext函数会判断

// 下一条记录是否存在,如果存在,指向下一条记录。否则,返回false。

while (cur.moveToNext()) {

// 取得联系人的ID索引值

String contactId =
cur.getString(cur

.getColumnIndex(ContactsContract.Contacts._ID));

if(contactId==null)

{

contactId="No Id";

}

// 取得联系人的名字索引

int nameIndex = cur.getColumnIndex(PhoneLookup.DISPLAY_NAME);

String name =
cur.getString(nameIndex);

if(name==null)

{

name="No name";

}

String rawContactsId = "";

String id = cur.getString(cur

.getColumnIndex(ContactsContract.Contacts._ID));

// str += "ID:" + id +
"\n";二、对联系人的基本操作(4)

// 读取rawContactsId

Cursor rawContactsIdCur =
cr.query(RawContacts.CONTENT_URI,

null, RawContacts.CONTACT_ID + " = ?",

new String[] { id }, null);

// 该查询结果一般只返回一条记录,所以我们直接让游标指向第一条记录

if (rawContactsIdCur.moveToFirst()) {

// 读取第一条记录的RawContacts._ID列的值

rawContactsId =
rawContactsIdCur.getString(rawContactsIdCur

.getColumnIndex(RawContacts._ID));

deleted =
rawContactsIdCur.getString(rawContactsIdCur

.getColumnIndex(RawContacts.DELETED));

version =
rawContactsIdCur.getString(rawContactsIdCur

.getColumnIndex(RawContacts.VERSION));

}

rawContactsIdCur.close();

// 读取号码

Cursor PhoneCur = cr.query(

ContactsContract.CommonDataKinds.Phone.CONTENT_URI,

null,

ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID

+ " =?", new String[] { rawContactsId }, null);

// 上面的ContactsContract.CommonDataKinds.Phone.CONTENT_URI

// 可以用下面的phoneUri代替

// Uri

// phoneUri=Uri.parse("content://com.android.contacts/data/phones");

// 二、对联系人的基本操作(6)

// 一个联系人可能有多个号码,需要遍历

if(!PhoneCur.moveToNext())

{

//获取电话号码为空的情况即游标未找到的情况

String  number="No number";

// // 获取号码类型

Map<String, Object>
map = new HashMap<String, Object>();

map.put("phone", number + ",");

map.put("name", name + "|");

map.put("version", version + ",");

map.put("deleted", deleted + ",");

map.put("id", contactId + ",");

list.add(map);

}

else

{

// 号获取码

String number = PhoneCur

.getString(PhoneCur

.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

// // 获取号码类型

Map<String, Object>
map = new HashMap<String, Object>();

map.put("phone", number + ",");

map.put("name", name + "|");

map.put("version", version + ",");

map.put("deleted", deleted + ",");

map.put("id", contactId + ",");

list.add(map);

}

while (PhoneCur.moveToNext()) {

// 号获取码

String number = PhoneCur

.getString(PhoneCur

.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

if(number==null)

{

number="No number";

}

// // 获取号码类型

Map<String, Object>
map = new HashMap<String, Object>();

map.put("phone", number + ",");

map.put("name", name + "|");

map.put("version", version + ",");

map.put("deleted", deleted + ",");

map.put("id", contactId + ",");

list.add(map);

}

PhoneCur.close();//关闭游标

}

}

return list;

}

}

时间: 2024-10-22 18:44:10

Android手机通讯录解析的相关文章

Android手机通讯录备份还原代码

实现方法很简单1.把通讯录中的联系人,电话号码保存到txt文件中完成备份.2.读取txt文件,导入到通讯录完成还原. 具体代码1.添加 通讯录读写权限,存储卡写权限 <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission><uses-permission android:name="android.permission.WRITE_EXT

Android手机通讯录项目开发--联系人数据库contacts2.db介绍

项目描述:该项目为基于Android平台的手机通讯录,主要模块分为四个部分:联系人管理模块,通话记录管理模块,短信管理模块,系统设置模块. 系统结构图如下: 本项目启动时间:2014年5月28日 说明:本次开发项目的所有源码全部会分享给大家.开发此项目的目的有这几点:一.锻炼独立开发项目的能力,二.增加对Android开发的了解,三.熟悉Android通讯录机制. 闲话不多说,正式开始! 技术要点一:熟悉Android联系人数据库contacts2.db 1.获得联系人数据库contacts2.

Android手机通讯录

1.概述 最近由于项目需求,需要做一个查看手机通讯录,并且取出相应的数据.类似于下图: 用到的一个主要的知识点:SectionIndexer--能够有效地帮助我们对分组进行控制,由于SectionIndexer是一个接口,你可以自定义一个子类来实现SectionIndexer, 不过自己再写一个SectionIndexer的实现太麻烦了,这里我们直接使用Android提供好 的实现AlphabetIndexer,用它来实现联系人分组功能已经足够了.AlphabetIndexer的构造函数需要传入

Android 手机卫士--解析json与消息机制发送不同类型消息

本文地址:http://www.cnblogs.com/wuyudong/p/5900800.html,转载请注明源地址. 1.解析json数据 解析json的代码很简单 JSONObject jsonObject = new JSONObject(json); //debug调试,解决问题 String versionName = jsonObject.getString("versionName"); mVersionDes = jsonObject.getString("

如何获得android手机通讯录的字母显示(两)

随后的写如何使各第一字母显示相同的分类触点: 于adapter implement SectionIndexer 这项adapter必须在下面可以实现3接口: @Override public Object[] getSections() { //section的集合 } @Override public int getPositionForSection(int section) {//当前section的位置 } @Override public int getSectionForPosit

Android 手机卫士--弹出对话框

在<Android 手机卫士--解析json与消息机制发送不同类型消息>一文中,消息机制发送不同类型的信息还没有完全实现,在出现异常的时候,应该弹出吐司提示异常,代码如下: private Handler mHandler = new Handler() { // public void handleMessage(android.os.Message msg) { switch (msg.what) { case UPDATE_VERSION: //弹出对话框,提示用户更新 //showUp

Android开发之获取手机通讯录

获取手机通讯录是Android最常用的小功能,今天自学到了,记下来,主要是通过系统自带的内容提供者提供的数据,我们使用内容接收者获取相应的数据到cursor中,然后获取对应data表中的字段,相关字段代表什么含义,只能自己去查了. 下面是手机通讯录列表的代码,仅供参考: package com.andy.phonecontact; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import

【Android Demo】简单手机通讯录

Android 系统给我们提供了访问通讯录的接口,通过接口获取通讯录信息.Adapter 与 View 的连接主要依靠 getView 这个方法返回我们需要的自定义 view. ListView 是 Android App 中一个最最最常用的控件了,所以如何让 ListView 流畅运行,获取良好的用户体验是非常重要的. 对 ListView 优化就是对 Adapter 中的 getView 方法进行优化. 核心内容: 1.获取手机通讯录 2.数据封装 3.创建 Adapter 4.优化适配器

Android开发系列(十一):对手机通讯录的读取、添加、删除、查找

一.通讯录介绍 通讯录是Android手机自带的一个应用,它是一个ContentProvider应用,其它应用可以对通讯录进行访问,进行对联系人的CRUD操作. 二.通讯录数据库结构的介绍 首先,我们可以在File Explorer视图下找到contacts2.db文件,这是通讯录的文件 然后,我们用SQLite打开,分析下它的数据库结构: raw_contacts表: data表: mimetypes表: 这三张表的结构介绍完了,接下来我们说下它们之间的联系: raw_contacts表存放联