Android基础笔记(十四)- 内容提供者读取联系人
利用内容提供者读取联系人
读取联系人相对于读取短信来说就复杂非常多了,我们一步一步来吧。
先看看一下联系人的数据库,是位于什么地方!
既然非常复杂,我们就一步步分析吧,我们把contacts2.db导出到电脑中,并使用SQLite数据库软件打开。
你能够看到一大堆的表和视图,当然我们使用到的也仅仅有三张。各自是raw_contacts、data、mimetypes分别存储着联系人ID、联系人数据、联系人数据相应的MIMIE类型。
我们逐个看一下,首先是raw_contacts表。 
 
在本表的contact_id列存储的是手机中联系人所相应的ID。通过上面的图能够知道,在手机中有两个联系人。
接下来看一下data表。
 
在本表中。我们最关心的有三列mimetype_id、raw_contact_id和data1。当中mimetype_id是mimetype表的主键ID;相应的raw_contact_id就是raw_contact的contact_id列了。
那么data1列代表的什么呢?
你猜的不错,就是我们联系人的数据。横向来看,raw_contact_id同样的行中data1列数据组成了一个联系人的数据。
在看一下mimetypes表的情况吧。 
 
也是比較简单。不同的mimetype内容代表的不同数据类型。比方:电话号、姓名、Email等。
看起来非常麻烦的样子,貌似还须要讲data表和mimetypes表联合查询才干够。
可是实际上不用这么麻烦,Google工程师已经为我们准备了view_data的视图,已经将data和mimetypes两张表的数据联结起来了。
我们赶紧看看里面的内容吧。
 
了解视图结构后,我们通过contact_id查询一下,就能够得到数据的内容和内容类型了。
分析完联系人的表,接下来就是怎样使用内容解析者去查询了,跟之前一样。依然要知道主机名和路径。
跟着我一起看一下源代码,这次联系人应用内容提供者的路径为android4.4\packages\providers\ContactsProvider。打开清单文件,能够看到例如以下信息:
 <provider android:name="ContactsProvider2"
    android:authorities="contacts;com.android.contacts"
    android:label="@string/provider_label"
    android:multiprocess="false"
    android:exported="true"
    android:readPermission="android.permission.READ_CONTACTS"
    android:writePermission="android.permission.WRITE_CONTACTS">
</provider>主机名是:com.andriod.contacts,记住别忘记加入读联系人和写联系人的权限。
再打开src\com\android\providers\contacts\ContactsProvider2.java文件,看一下路径是什么。
static {
    // Contacts URI matching table
     matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts", RAW_CONTACTS);
     matcher.addURI(ContactsContract.AUTHORITY, "raw_contacts/#", RAW_CONTACTS_ID);
    ... ...
     matcher.addURI(ContactsContract.AUTHORITY, "data", DATA);
     matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID);
     ... ...
}能够得知,查看raw_contacts的路径就是raw_contacts,查看data表的路径就是data。
- 该准备的东西都准备完成了。那么就进入到代码的步骤吧。
- ① 在raw_contacts表中查询出来联系人的ID集合
- ② 以联系人ID为过滤条件,在view_data视图中,查找mimetype和data1
下面是代码:
// 在raw_contacts表中查询出来联系人的ID集合
Uri rawContactsUri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri viewDataUri = Uri.parse("content://com.android.contacts/data");
Cursor rawContactsCursor = getContentResolver().query(rawContactsUri, null, null, null, null);
if (rawContactsCursor != null) {
    while (rawContactsCursor.moveToNext()) {
        int columnIndex = rawContactsCursor.getColumnIndex("contact_id");
        String contact_id = rawContactsCursor.getString(columnIndex);
        // System.out.println("联系人ID:" + contact_id);
        // 以联系人ID为过滤条件。在view_data视图中,查找mimetype和data1
        Cursor viewDataCursor = getContentResolver().query(viewDataUri, new String[] { "mimetype", "data1" }, "contact_id=?", new String[] { contact_id }, null);
        if (viewDataCursor != null) {
            while (viewDataCursor.moveToNext()) {
                String mimetype = viewDataCursor.getString(0);
                String data1 = viewDataCursor.getString(1);
                if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
                    System.out.println("联系人ID:" + contact_id + ",电话:" + data1);
                } else if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
                    System.out.println("联系人ID:" + contact_id + ",email:" + data1);
                } else if ("vnd.android.cursor.item/name".equals(mimetype)) {
                    System.out.println("联系人ID:" + contact_id + ",联系人姓名:" + data1);
                }
            }
            viewDataCursor.close();
        }
    }
    rawContactsCursor.close();
}利用内容提供者插入联系人
- 插入联系人分为下面几步:
- ①手动插入联系人ID;ID值为数据库中总条目数加1。
- ②再依次向data表中插入联系人数据。
总体的代码还是比較清晰地,请看下吧:
String name = et_name.getText().toString().trim();
String phone = et_phone.getText().toString().trim();
int contact_id = 0;
Uri rawContactsUri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri viewDataUri = Uri.parse("content://com.android.contacts/data");
// 手动插入联系人ID;ID值为数据库中总条目数加1。
Cursor rawContactsCursor = getContentResolver().query(rawContactsUri, null, null, null, null);
if (rawContactsCursor != null) {
    int count = rawContactsCursor.getCount();
    contact_id = count + 1;
    rawContactsCursor.close();
}
// 插入联系人ID
ContentValues values = new ContentValues();
values.put("contact_id", contact_id);
getContentResolver().insert(rawContactsUri, values);
// 再依次向`data`表中插入联系人数据。
ContentValues nameValues = new ContentValues();
nameValues.put("raw_contact_id", contact_id);
nameValues.put("mimetype", "vnd.android.cursor.item/name");
nameValues.put("data1", name);
getContentResolver().insert(viewDataUri, nameValues);
ContentValues phoneValues = new ContentValues();
phoneValues.put("raw_contact_id", contact_id);
phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
phoneValues.put("data1", phone);
getContentResolver().insert(viewDataUri, phoneValues);以上都是演示样例代码,假设要实际使用还须要做非常多非常多工作。
内容观察者的原理
ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理。它相似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时。便会触发它。
- 使用ContentObserver的情况主要有一下两者情况:
- ①须要频繁检測的数据库或者某个数据是否发生改变,假设使用线程去操作。非常不经济并且非常耗时 。
- ②在用户不知晓的情况下对数据库做一些事件。比方:悄悄发送信息、拒绝接受短信黑名单等;
利用内容观察者监听系统应用数据库或者自己应用数据库的变化
这里就给出一个简单的样例吧。博主的学识还是太浅了,刚才浏览了网上一些人写的内容观察者的博客,认为自己会的东西还是太少了。小小总结一下。
当以后用到的时候再细致的总结。
使用观察者监听系统应用的变化
监听数据库的变化,主要使用到了ContentResler类中的registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)方法。
第一个參数是我们监视的Uri。第二个參数为true时会匹配全部以我们指定的Uri开头的地址,第三个參数就是我们的观察者了。
假设我们要监听系统短信数据库的变化,能够这么做:
Uri uri = Uri.parse("content://sms");
getContentResolver().registerContentObserver(uri, true, new ContentObserver(new Handler()) {
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        System.out.println("短信内容发生改变了");
    }
});已经知道了怎样监视一个Uri的变化后,监听我们自己应用数据库的变化,仅仅须要将Uri改动一下就能够了。可是,这里还差一步。当我们通过内容提供者去訪问已有数据后,还要通知一下,这样才干够让观察者接收到内容改变的消息。
这里就使用到了ContentReslover中的notifyChange(Uri uri, ContentObserver observer)方法。
// 提供给外部应用调用的查询方法
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    int MATCH_CODE = MURI_MATCHER.match(uri);
    if (MATCH_CODE == QUERY_SUCCESS) {
        // 大喊一声,数据发生改变了
        getContext().getContentResolver().notifyChange(uri, null);
        return db.query(ACCOUNT, projection, selection, selectionArgs, null, null, sortOrder);
    }
    return null;
}这两篇博客写的比較仓促,请多多包括了。
Android基础笔记(十四)- 内容提供者读取联系人的更多相关文章
- <Android 基础(十四)> selector
		介绍 A StateListDrawable is a drawable object defined in XML that uses a several different images to r ... 
- 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版
		目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ... 
- Bootstrap<基础二十四> 缩略图
		Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ... 
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
		python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ... 
- 《C++游戏开发》笔记十四 平滑过渡的战争迷雾(二) 实现:真正的迷雾来了
		本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9712321 作者:七十一雾央 新浪微博:http:/ ... 
- Android初级教程之内容提供者获取联系人信息
		内容提供折详细理论知识请参考之前的博文:http://blog.csdn.net/qq_32059827/article/details/51646513 这里新建了三个联系人信息,通过查看系统联系人 ... 
- Java15-java语法基础(十四)抽象类
		Java15-java语法基础(十四)抽象类 一.抽象类的作用 三个类都有"执行任务"的方法,分别在这三个类中进行定义,因此需要重复编写代码,降低了程序开发效率,且增加了程序出现错 ... 
- Android基础笔记(十三)- 内容提供者原理和简单使用
		为什么要有内容提供者 内容提供者的工作原理 使用内容解析者对内容提供者进行增删改查操作 利用内容提供者和内容解析者备份手机短信 利用内容提供者插入短信 为什么要有内容提供者 内容提供者技术的目的是: ... 
- Android应用开发基础之九:内容提供者(ContentProvider)
		内容提供者 应用的数据库是不允许其他应用访问的 内容提供者的作用:就是让别的应用访问到你的数据库 自定义内容提供者,继承ContentProvider类,重写增删改查方法,在方法中写增删改查数据库的代 ... 
随机推荐
- [LeetCode OJ] Best Time to Buy and Sell Stock I
			Say you have an array for which the ith element is the price of a given stock on day i. If you were ... 
- Dynamic Web Module 3.0 requires Java 1.6 or newer报错
			在项目的pom.xml的<build></build>标签中加入: <plugins> <plugin> <groupId>org.apac ... 
- PHP图片操作
			<?php $filename="http://pic.nipic.com/2007-12-06/2007126102233577_2.jpg";//图片地址//获取图片信息 ... 
- Python Tutorial 学习(六)--Modules
			6. Modules 当你退出Python的shell模式然后又重新进入的时候,之前定义的变量,函数等都会没有了. 因此, 推荐的做法是将这些东西写入文件,并在适当的时候调用获取他们. 这就是为人所知 ... 
- uboot的jumptable_init函数分析
			一.函数说明 函数功能:安装系统函数指针 函数位置:common/exports.c 二.函数分析 void jumptable_init (void) { int i; gd->jt = (v ... 
- bzoj3639: Query on a tree VII
			Description You are given a tree (an acyclic undirected connected graph) with n nodes. The tree node ... 
- redis运行状态图形化监控工具 — RedisLive
			在Centos中部署redis运行状态图形化监控工具 — RedisLive 写在前面 前两天看到张善友老师的一篇文章<先定个小目标, 使用C# 开发的千万级应用>,里面给出了一张腾讯 ... 
- UIProgressView
			UIProgressView顾名思义用来显示进度的,如音乐,视频的播放进度,和文件的上传下载进度等. 下面以一个简单的实例来介绍UIprogressView的使用. @interface Activi ... 
- ios中关于delegate(委托)的使用心得
			ios中关于delegate(委托)的使用心得 分类: iOS开发2012-05-15 10:54 34793人阅读 评论(9) 收藏 举报 iosuiviewtimerinterfaceprinti ... 
- 最新iOS 6 in Xcode4.5新特性——Storyboard和属性自动绑定
			最新iOS 6 in Xcode4.5新特性编程之二(上)——Storyboard和属性自动绑定 从Xcode 4.3开始,Storyboard 就是iOS 5和iOS 6中令人兴奋的一个新特性,他将 ... 
