我们学了 Android 数据持久化的技术,包括文件存储、SharedPreferences 存 储、以及数据库存储。不知道你有没有发现,使用这些持久化技术所保存的数据都只能在当 前应用程序中访问。虽然文件和 SharedPreferences 存储中提供了 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 这两种操作模式,用于供给其他的应用程序访问当前应用 的数据,但这两种模式在 Android 4.2 版本中都已被废弃了。为什么呢?因为 Android 官方已 经不再推荐使用这种方式来实现跨程序数据共享的功能,而是应该使用更加安全可靠的内容 提供器技术。
可能你会有些疑惑,为什么要将我们程序中的数据共享给其他程序呢?当然,这个要视 情况而定的,比如说账号和密码这样的隐私数据显然是不能共享给其他程序的,不过一些可 以让其他程序进行二次开发的基础性数据,我们还是可以选择将其共享的。例如系统的电话 簿程序,它的数据库中保存了很多的联系人信息,如果这些数据都不允许第三方的程序进行 访问的话,恐怕很多应用的功能都要大打折扣了。除了电话簿之外,还有短信、媒体库等程 序都实现了跨程序数据共享的功能,而使用的技术当然就是内容提供器了,下面我们就来对 这一技术进行深入的探讨。
内容提供器简介
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能, 它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据 的安全性。目前,使用内容提供器是 Android 实现跨程序共享数据的标准方式。
不同于文件存储和 SharedPreferences 存储中的两种全局可读写操作模式,内容提供器可 以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。
内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中 的数据,另一种是创建自己的内容提供器给我们程序的数据提供外部访问接口。那么接下来 我们就一个一个开始学习吧,首先从使用现有的内容提供器开始。
7.2 访问其他程序中的数据
当一个应用程序通过内容提供器对其数据提供了外部访问接口,任何其他的应用程序就 都可以对这部分数据进行访问。Android 系统中自带的电话簿、短信、媒体库等程序都提供 了类似的访问接口,这就使得第三方应用程序可以充分地利用这部分数据来实现更好的功
能。下面我们就来看一看,内容提供器到底是如何使用的。
7.2.1 ContentResolver 的基本用法
对于每一个应用程序来说,如果想要访问内容提供器*享的数据,就一定要借助 ContentResolve 类,可以通过
Context 中的 getContentResolver() 方法获取到该类的实例。 ContentResolver 中提供了一系列的方法用于对数据进行 CRUD 操作,其中 insert()方法用于 添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数 据。有没有似曾相识的感觉?没错,SQLiteDatabase 中也是使用的这几个方法来进行 CRUD 操作的,只不过它们在方法参数上稍微有一些区别。
不同于 SQLiteDatabase,ContentResolver 中的增删改查方法都是不接收表名参数的,而
是使用一个 Uri 参数代替,这个参数被称为内容 URI。内容 URI
给内容提供器中的数据建立
了唯一标识符,它主要由两部分组成,权限(authority)和路径(path)。权限是用于对不同
的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。比如某个
程序的包名是 com.example.app ,那么该程序对应的权限就可以命名为 com.example.app. provider。路径则是用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。
比如某个程序的数据库里存在两张表,table1 和 table2,这时就可以将路径分别命名为/table1
和/table2,然后把权限和路径进行组合,内容 URI 就变成了 com.example.app.provider/table1 和 com.example.app.provider/table2。不过,目前还很难辨认出这两个字符串就是两个内容 URI,我们还需要在字符串的头部加上协议声明。因此,内容 URI 最标准的格式写法如下:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
有没有发现,内容 URI 可以非常清楚地表达出我们想要访问哪个程序中哪张表里的数 据。也正是因此,ContentResolver 中的增删改查方法才都接收 Uri 对象作为参数,因为使用 表名的话系统将无法得知我们期望访问的是哪个应用程序里的表。
在得到了内容 URI 字符串之后,我们还需要将它解析成 Uri 对象才可以作为参数传入。 解析的方法也相当简单,代码如下所示:
Uri uri = Uri.parse("content://com.example.app.provider/table1")
只需要调用 Uri.parse()方法,就可以将内容 URI 字符串解析成 Uri 对象了。
现在我们就可以使用这个 Uri 对象来查询 table1 表中的数据了,代码如下所示:
Cursor cursor = getContentResolver().query(
uri,
projection, selection, selectionArgs,
sortOrder);
这些参数和 SQLiteDatabase 中 query()方法里的参数很像,但总体来说要简单一些,毕 竟这是在访问其他程序中的数据,没必要构建过于复杂的查询语句。下表对使用到的这部分
参数进行了详细的解释。
query()方法参数 |
对应 SQL 部分 |
描述 |
uri |
from table_name |
指定查询某个应用程序下的某一张表 |
projection |
select column1, column2 |
指定查询的列名 |
selection |
where column = value |
指定 where 的约束条件 |
selectionArgs |
- |
为 where 中的占位符提供具体的值 |
orderBy |
order by column1, column2 |
指定查询结果的排序方式 |
查询完成后返回的仍然是一个 Cursor 对象,这时我们就可以将数据从 Cursor 对象中逐
个读取出来了。读取的思路仍然是通过移动游标的位置来遍历 Cursor 的所有行,然后再取出 每一行中相应列的数据,代码如下所示:
if (cursor != null) {
while (cursor.moveToNext()) {
String column1 = cursor.getString(cursor.getColumnIndex("column1"));
int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
}
cursor.close();
}
掌握了最难的查询操作,剩下的增加、修改、删除操作就更不在话下了。我们先来看看 如何向 table1 表中添加一条数据,代码如下所示:
ContentValues values = new
ContentValues(); values.put("column1", "text");
values.put("column2", 1); getContentResolver().insert(uri, values);
可以看到,仍然是将待添加的数据组装到 ContentValues 中,然后调用 ContentResolver的 insert()方法,将 Uri
和 ContentValues 作为参数传入即可。
现 在 如 果 我 们 想 要 更 新 这 条 新 添 加 的 数 据 , 把 column1 的 值 清 空 , 可 以 借 助
ContentResolver 的 update()方法实现,代码如下所示:
ContentValues values = new ContentValues();
values.put("column1", "");
getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new
String[] {"text", "1"});
注意上述代码使用了 selection 和 selectionArgs 参数来对想要更新的数据进行约束,以防
止所有的行都会受影响。
最后,可以调用 ContentResolver 的 delete()方法将这条数据删除掉,代码如下所示:
getContentResolver().delete(uri, "column2 = ?", new
String[] { "1" });
到这里为止,我们就把 ContentResolver 中的增删改查方法全部学完了。是不是感觉非常
简单?因为这些知识早在上一章中学习 SQLiteDatabase 的时候你就已经掌握了,所需特别注
意的就只有 uri 这个参数而已。
android: 内容提供器简介的更多相关文章
-
Android 内容提供器(Content Provider)介绍
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性.目前,使用内容 ...
-
Android学习之基础知识十—内容提供器(Content Provider)
一.跨程序共享数据——内容提供器简介 内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能 ...
-
入职小白随笔之Android四大组件——内容提供器详解(Content Provider)
Content Provider 内容提供器简介 内容提供器(Content Provider)主要用于在不同的应用程序之间 实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的 ...
-
5、Android-跨程序共享数据--内容提供器
Android数据持久化技术:文件存储.SharedPreferences存储.数据库存储 使用这些持久化技术保存的数据只能再当前的应用程序中访问 但是对于不同应用之间的可以实现跨程序数据共享的功能 ...
-
Android之 内容提供器(2)——创建自己的内容提供器将数据共享出去
创建自己的内容提供器非常简单,只需要新建一个类继承ContentProvider类,通过实现ContentProvider的增删改查的方法向内容提供器中增删数据. 1 ContentProvider简 ...
-
Android之 内容提供器(1)——使用内容提供器访问其它程序共享的数据
(下面内容是阅读郭霖大神的<第一行代码>总结的) 1 概述 内容提供器是Android实现跨程序共享数据的标准方式. 内容提供器的的使用方法有两种, 一是使用已有的内容提供器对其他程序的数 ...
-
Android入门(十四)内容提供器-实现跨程序共享实例
原文链接:http://www.orlion.ga/661/ 打开SQLite博文中创建的 DatabaseDemo项目,首先将 MyDatabaseHelper中使用 Toast弹出创建数据库成功的 ...
-
Android入门(十三)内容提供器
原文链接:http://www.orlion.ga/612/ 内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一 ...
-
Android学习笔记(二十)——自定义内容提供器
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 如果我们想要实现跨程序共享数据的功能,官方推荐的方式就是使用内容提供器,可以通过新建一个类去继承 Conten ...
随机推荐
-
C#学习资源
# 视频 C#程序设计 Cousera(推荐) # 文档 C#教程 MSDN Microsoft API 和参考目录
-
POJ 3278 Catch That Cow
注:本人英语很渣,题目大意大多来自百度~=0= 题目大意 农民约翰需要抓住他的牛,他和他的牛在一条直线上(估计是一维生物),约翰在N (0 ≤ N ≤ 100,000)处,他的牛在 K (0 ≤ K ...
-
基于<;MediaElement>;的WPF视频播放器(可拖拽进度条播放)【1】
一.前言 前两天上峰要求做一个软件使用向导,使用WPF制作.这不,这两天从一张白纸开始学起,做一个播放演示视频的使用向导.以下是粗设计的原型代码: 二.效果图 三.代码 前台代码: < ...
-
MathType的公式在word中跟文字不对齐
引用http://blog.sina.com.cn/s/blog_4d1f40c00100net8.html 部分Mathtype公式与文档文字没有很好的对齐,而是浮起来了,也就是说Mathtype公 ...
-
upgrade-php-5-1-to-php-5-3-using-yum-on-centos
wget -q -O - http://www.atomicorp.com/installers/atomic | shyum upgrade phpyum -y remove atomic-rele ...
-
codeforces 278Div1 B题
虚拟参赛的时候没想到是线段树,看到很多人都过了,也蛮着急的. 首先用二分+线段树的方法更新DP[i]:它表示以A[i]为结尾可以最前到哪个位置: 再用线段树计算ans[i]:它表示当前i个A元素可以最 ...
-
Duanxx的STM32学习: 启动模式,BOOT0和BOOT1具体解释
在画STM32的电路图的时候,关于STM32的启动方式纠结了一下,现有的參考设计都是在STM32的启动选择引脚BOOT0和BOOT1上使用了跳帽,用以人工选择STM32的启动方式,可是在实际应用中这样 ...
-
Numpy random arange zeros
seed( ) 用于指定随机数生成时所用算法开始的整数值. .如果使用相同的seed( )值,则每次生成的随即数都相同: .如果不设置这个值,则系统根据时间来自己选择这个值,此时每次生成的随机数因时间 ...
-
Linux下安装LAMP(Apache+PHP+MySql)和禅道
1.更新yum源: yum update -y 2.安装Apache+PHP+MySql yum install httpd mysql-devel mysql-server mysql-php ph ...
-
HDU 2516 取石子游戏 (找规律)
题目链接 Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出" ...