文档章节

Android四大组件-ContentProvider

北ing
 北ing
发布于 2015/10/20 19:23
字数 1975
阅读 18
收藏 1
点赞 0
评论 0

ContentProvider:内容提供者

ContentProvider简介:
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
Uri类简介
Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。
2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
• 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
• 要操作contact表中id为10的记录的name字段, contact/10/name
• 要操作contact表中的所有记录,可以构建这样的路径:/contact

本篇主要围绕通话记录和联系人讲解ContentProvider的使用。

首先来了解一下通话记录和联系人的表结构。
这是手机中部分表:
这里写图片描述
通话记录在calls表中,联系人表主要有三个:raw_contacts、data、mimetype表。
–联系人记录
–存放联系人信息的表(注意表结构):
联系人信息表:raw_contacts
–_id
–display_name联系人名称

联系人数据表:data
–_id
–raw_contact_id(外键,raw_contacts表的_id)
–data1
–data2
–mimetype_id(数据类型,如电话,邮箱,地址 外键(mimeypes))

数据类型表:mimeypes
–_id
–mimetype
这里写图片描述
数据类型表中需要注意的是name、phone_v2、email_v2字段,对应id是7、5、1;


一、ContentResolver的使用

1)定义ContentProvieder组件提供的内容的Uri接口
2)定义被访问的表中的字段
3)添加访问权限

简单使用1:查询最近联系人记录

// 访问拨号应用下的ContentProvieder组件提供的内容的Uri接口
private Uri callUri = CallLog.Calls.CONTENT_URI;
// 被访问的表中的字段
private String[] columns = { CallLog.Calls._ID, CallLog.Calls.NUMBER,
CallLog.Calls.DATE, CallLog.Calls.TYPE };

private void loadData() {
        // 使用ContentResolver访问拨号记录应用下的ContentProvider组件提供的数据库中表的数据
        // 得到ContentResolver对象
        ContentResolver resolver = getContentResolver();
        // 查询uri代表的资源(从 Uri代表的表中进行查询)
        Cursor cursor = resolver.query(callUri, columns, null, null, null);
        while (cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String number = cursor.getString(1);
            long time = cursor.getLong(2);
            int type = cursor.getInt(3);
            String date = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss")
                    .format(new Date(time));
            String types = (type == 1 ? "拨入" : (type == 2 ? "拨出" : "未接"));
            datas.add(new CallInfo(id, number, date, types));
        }
        adapter.notifyDataSetChanged();
    }

简单使用2:查询手机联系人,然后执行增删改操作
需要了解联系人数据库中有哪些表及表的结构:通过adb shell可以查看。
–联系人记录
–存放联系人信息的表(注意表结构):
联系人信息表:raw_contacts
–_id
–display_name联系人名称
联系人数据表:data
–_id
–raw_contact_id(外键,raw_contacts表的_id)
–data1:电话、邮箱、姓名等信息
–data2
–mimetype_id(数据类型,如电话,邮箱,地址 外键(mimeypes))
数据类型表:mimeypes
–_id
–mimetype
– mimetype_id=1:邮箱
– mimetype_id=5:电话
– mimetype_id=7:姓名

// 访问raw_contacts这张表的Uri
    private Uri contactUri = Uri            .parse("content://com.android.contacts/raw_contacts");
    private String[] conColumn = { "_id", "display_name" };
    // //访问data这张表的Uri
    private Uri dataUri = Uri.parse("content://com.android.contacts/data");
    private String[] dataColumn = { "data1" };

—>增删该查操作都是第一步得到ContentResolver操作对象,第二步执行已经定义好的方法。

<!-- 访问联系人的ContentProvider组件的权限 -->
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

2.1添加联系人:
// 向联系人表raw_contacts中添加新的联系人信息

ContentValues value = new ContentValues();
value.put("display_name", name);
value.put("display_name_alt", name);
// 返回新插入的记录Uri,Uri中包含了_id
// content://com.android.contacts/raw_contacts/#8
    Uri datasUri = getContentResolver().insert(contactUri,value);

这个方法值得注意的是返回的是一个uri,也就是新增的这条数据的uri,如果想得到该条记录的id可以调用这个方法:
long _id = ContentUris.parseId(datasUri);

–姓名:
value.put(“data1”, name);
value.put(“mimetype”,”vnd.android.cursor.item/name”);
–电话:
value.put(“data1”, phone);
value.put(“mimetype”,”vnd.android.cursor.item/phone_v2”);
–邮件:
value.put(“data1”, email);
value.put(“mimetype”,”vnd.android.cursor.item/email_v2”);

2.2删除联系人:都是很简单的操作
// 再从联系人表中删除信息
getContentResolver().delete(contactUri, “_id=” + id,null);

2.3修改联系人:

value.put("display_name", name);
value.put("display_name_alt", name);
long id = Long.parseLong(String.valueOf(datas.get(curItemPosition).get("id")));
// 更新联系人信息
getContentResolver().update(contactUri, value,"_id=" + id, null);

2.4查询所有联系人

ContentResolver resolver = getContentResolver();
// 先从联系人表中查询所有人的信息
Cursor cursor = resolver.query(contactUri, conColumn, null, null, null);

二、自定义ContentProvider

1.步骤:
1)声明该contentProvider的唯一标识,通常使用包名加数据库名,必须小写
2)为该组件中可以被外界访问的数据库中的资源定义Code标识,不对外界开放的不用定义
3)定义访问资源的Uri的匹配器对象–使用该类生成被访问的资源的Uri
4)UriMatcher添加访问uri
5)清单文件中注册组件 name authorities
6)声明访问该组件的权限
7)重写provider的增删改查方法

2.实现
1)自定义数据库

public class DBHelper extends SQLiteOpenHelper {
    public DBHelper(Context context) {
        super(context, "users.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO 初始化数据库
        db.execSQL("create table t_user(_id integer primary key,uname,upass,money)");
        db.execSQL("create table t_order(_id integer primary key,user_id,price,productname)");
        db.execSQL("insert into t_user(uname,upass,money) values('lisa','123',200)");
        db.execSQL("insert into t_user(uname,upass,money) values('zhangsan','1234',2000)");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO 数据库升级时执行该方法
        if (newVersion > oldVersion) {
            db.execSQL("drop table if exists t_user");
            db.execSQL("drop table if exists t_order");
            onCreate(db);
        }
    }
}

2)按上述步骤定义ContentProvider

public class UserContentProvider extends ContentProvider {
    // 声明该ContentProvider的唯一标识--通常使用包名+数据库名--必须小写
    public static final String AUTHORITY = "com.beiing.contentprovider_selfdefine.users";
    // 为该组件中可以被外界访问的数据库中的资源定义Code标识
    public static final int CODE_USER = 1;
    public static final int CODE_ORDER = 2;
    // 定义访问资源的Uri的匹配器对象--使用该类生成被访问的资源的Uri
    private static UriMatcher uriMatcher;
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        // content://com.beiing.contentprovider_selfdefine.users/user
        uriMatcher.addURI(AUTHORITY, "user", CODE_USER);
        // content://com.beiing.contentprovider_selfdefine.users/order
        uriMatcher.addURI(AUTHORITY, "order", CODE_ORDER);
    }
    private DBHelper dbHelper;
    @Override
    public boolean onCreate() {
        // TODO 初始化 数据库操作的工具类
        dbHelper = new DBHelper(getContext());
        return false;
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = null;
        int code = uriMatcher.match(uri);
        switch (code) {
        case CODE_USER:
            cursor = db.query("t_user", projection, selection, selectionArgs,
                    null, null, sortOrder);
            break;
        case CODE_ORDER:
            break;
        }
        return cursor;
    }
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO 向数据库中插入数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        if (uriMatcher.match(uri) == CODE_USER) {
            long id = db.insert("t_user", null, values);
            // 返回新插入的记录的 Uri,回忆插入新数据时可以通过返回的uri得到id
            // content://com.beiing.contentprovider_selfdefine.users/user/6
            return ContentUris.withAppendedId(uri, id);
        }
        return null;
    }
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO 删除数据库中的数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int num = 0;
        if (uriMatcher.match(uri) == CODE_USER) {
            num = db.delete("t_user", selection, selectionArgs);
        }
        return num;
    }
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO 修改数据库中的数据
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        if (uriMatcher.match(uri) == CODE_USER) {
            return db.update("t_user", values, selection, selectionArgs);
        }
        return 0;
    }
    @Override
    public String getType(Uri uri) {
        return null;
    }
}

3)清单文件中注册内容提供器

<!-- 注册 ContentProvider组件 android:authorities:声明该组件的唯一标识 android:permission:声明该组件的权限 android:exported="true":声明该组件可以被外界应用访问 -->
<provider android:name="com.beiing.contentprovider_selfdefine.contentprovider.UserContentProvider" android:authorities="com.beiing.contentprovider_selfdefine.users" android:permission="com.beiing.contentprovider_selfdefine.READ_WRITE" android:exported="true" />

注意:还需要添加访问该provider的权限和修改的操作权限,否则其他程序不能访问或操作

<!-- 声明访问该组件的权限 -->
    <permission android:name="com.beiing.contentprovider_selfdefine.READ_WRITE"/>

4)在其他程序中使用
和上面使用类似,不赘述了。

源码

版权声明:本文为博主原创文章,未经博主允许不得转载。

© 著作权归作者所有

共有 人打赏支持
北ing
粉丝 0
博文 12
码字总数 17332
作品 0
海淀
小白入门Android必须知道的四大组件

学习App开发从布局入手之后,以能够顺利识别并搭建一个页面所需要的UI组件为目标。但是搭建好的不同界面间如何切换呢?不同界面间的数据是如何传递的呢?除了我们看到的界面,App后台还能做其...

冬风破10 ⋅ 01/12 ⋅ 0

通读《疯狂Android讲义》笔记 01 ___Android基础篇

文 | 莫若吻 注: 1.本文内容参考 李刚的《疯狂Android讲义》一书。 2.此书适合有一定Java基础、初学Android的同学阅读与学习。我最近想巩固下Android基础知识就来拜读一下此书。 3.本文笔记...

莫若吻 ⋅ 2017/11/06 ⋅ 0

要点提炼|开发艺术之四大组件

提到四大组件大家肯定再熟悉不过了,本篇侧重于对四大组件工作过程的分析: 概述 工作过程 Activity Service BroadcastReceiver ContentProvider 1.概述 a.Activity 类型:展示型组件。 作用...

minmin_1123 ⋅ 2017/12/27 ⋅ 0

读博文学Android

学习Android的过程中得到来自互联网上乐于分享和奉献的人们的帮助,这里收集了一些Android相关的知识点的介绍,研究,实践的博文地址。每篇文章将带给学习者更多的帮助,有些地址需要FQ的帮助...

secondriver ⋅ 2015/12/18 ⋅ 0

android四大组件(详细总结)

android四大组件分别为activity、service、content provider、broadcastreceiver。 一、android四大组件详解 1、activity (1)一个Activity通常就是一个单独的屏幕(窗口)。 (2)Activit...

Sheamus ⋅ 2015/09/28 ⋅ 0

Android四大组件(详细总结)

Android四大组件分别为activity、service、content provider、broadcast receiver。 一、Android四大组件详解 1、activity (1)一个Activity通常就是一个单独的屏幕(窗口)。 (2)Activit...

天蚕宝衣 ⋅ 2016/06/28 ⋅ 0

【Android学习总结】之Activity:初识Activity及使用

【本博客内的文章是本人的学习笔记总结,如有错误请各位批评指正,谢谢!欢迎加入群285077071讨论】 一、Activity的目的(功能) Activity是Android系统中四大组件(四大组件为:Activity,S...

kinbos ⋅ 2015/10/14 ⋅ 0

彻底认识 PendingIntent

最近在写一个闹钟程序的时候使用到了 PendingIntent, 而且是两个地方用到,一个是 AlarmManager 定时的时候, 另一个是在点击通知进入应用的时候。其实我早就想深入研究一下 PendingIntent...

Jinux111 ⋅ 05/25 ⋅ 0

Android面试笔记基础篇

基础一:安卓四大组件。 问题一:安卓四大组件是什么?应该怎么描述它们?生命周期?优先级? 答:四大组件就是Activity Service BroadCastReciver ContentProvider Activity:与用户交互等界...

一阵啪啪啪 ⋅ 01/15 ⋅ 0

Android 【插件化】"偷梁换柱"的高手-VirtualApk源码解析

关于VirtualApk VirtualApk github : https://github.com/didi/VirtualAPK VirtualAPK wiki : https://github.com/didi/VirtualAPK/wiki 工程介绍 工程结构 CoreLibrary是VirtualApk(以下简称......

qq_17250009 ⋅ 04/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

笔试题之Java基础部分【简】【一】

基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他 1.length、length()和size() length针对...

anlve ⋅ 22分钟前 ⋅ 2

table eg

user_id user_name full_name 1 zhangsan 张三 2 lisi 李四 `` ™ [========] 2018-06-18 09:42:06 星期一½ gdsgagagagdsgasgagadsgdasgagsa...

qwfys ⋅ 47分钟前 ⋅ 0

一个有趣的Java问题

先来看看源码: public class TestDemo { public static void main(String[] args) { Integer a = 10; Integer b = 20; swap(a, b); System.out......

linxyz ⋅ 51分钟前 ⋅ 0

十五周二次课

十五周二次课 17.1mysql主从介绍 17.2准备工作 17.3配置主 17.4配置从 17.5测试主从同步 17.1mysql主从介绍 MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主...

河图再现 ⋅ 今天 ⋅ 0

docker安装snmp rrdtool环境

以Ubuntu16:04作为基础版本 docker pull ubuntu:16.04 启动一个容器 docker run -d -i -t --name flow_mete ubuntu:16.04 bash 进入容器 docker exec -it flow_mete bash cd ~ 安装基本软件 ......

messud4312 ⋅ 今天 ⋅ 0

OSChina 周一乱弹 —— 快别开心了,你还没有女友呢。

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享吴彤的单曲《好春光》 《好春光》- 吴彤 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :小萝莉街上乱跑,误把我认错成...

小小编辑 ⋅ 今天 ⋅ 8

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部