博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ContentProvider 增删改查通讯录
阅读量:5246 次
发布时间:2019-06-14

本文共 8411 字,大约阅读时间需要 28 分钟。

一、通讯录应用介绍

 

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

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

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

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

 

二、获取ContactProvider的源代码

 
 

Android源代码:    用获取;

如果要获取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]   
 
  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.

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]   
 
  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]   
 
  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]   
 
  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", "xzdong@xzdong.com");  
  29.         resolver.insert(uri, values);  
  30.     }  
 
(2)批量添加数据
 
核心代码:
(1)ContentProviderOperation operation = ContentProviderOperation.newInsert(uri).withValue("key","value").build();
(2)resolver.applyBatch("authorities",operations);//批量提交
 
[java]   
 
  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]   
 
  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]   
 
    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. }  

转载于:https://www.cnblogs.com/jingmo0319/p/5600057.html

你可能感兴趣的文章
Leetcode 92. Reverse Linked List II
查看>>
TensorFlow2-维度变换
查看>>
Redux源码分析之createStore
查看>>
POJ 2060 最小路径覆盖
查看>>
label标签作用
查看>>
Selenium2之Web自动化编写配置(Java)
查看>>
windown快速安装xgboost
查看>>
tarjan(缩点)
查看>>
Lombok插件
查看>>
Linux上安装Libssh2
查看>>
自定义EL函数
查看>>
stm32的电源
查看>>
splice的多种用法
查看>>
20162304 2017-2018-1 《程序设计与数据结构》第二周学习总结
查看>>
九.python面向对象(双下方法内置方法)
查看>>
2018-09-12
查看>>
go:channel(未完)
查看>>
[JS]递归对象或数组
查看>>
CSS与Theme的作用——Asp.Net
查看>>
LeetCode(17) - Letter Combinations of a Phone Number
查看>>