Android学习--跨程序共享数据之内容提供其探究
什么是内容提供器?
跨程序共享数据之内容提供器,这是个什么功能?看到这个名称的时候最能给我们提供信息的应该是“跨程序”这个词了,是的重点就是这个词,这个内容提供器的作用主要是用于在不同的引用程序之间实现数据共享的功能,它提供了一完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问的数据的安全性,在目前使用内容提供器是Android实现跨程序共享数据的标准方式。不同于文件存储和SharePreferences存储中的两种全局可读性操作模式,内容提供器可以选择只对那一部分数据进行共享,从而保证我们程序中的隐私数据不糊有泄漏的风险。
不过在理解这个内容提供器之前,我们需要理解Android的运行时权限,这个就不需要我们解释什么是运行时权限了,因为我们在之前其实已经使用过,比如“相机权限”,“照片权限”,“位置权限”等等!
运行时权限
Android 将所有的权限大致的分为两类,一类是普通权限,另一类是危险权限,我们在下面将危险的权限整理了出来,供以后我们参考使用:

举个小栗子
下面是针对打电话我们写的一个小Demo,其实逻辑很简单,说的直接点就是一句话“有权限直接打电话,没有权限就请求完了再打”。下面是点击事件我们做的操作
// 利用checkSelfPermission这个函数检查有没有运行时权限
// 有权限就直接调用下面的call()方法,没有就请求权限
// checkSelfPermission(MainActivity.this, android.Manifest.permission.CALL_PHONE) 是否等于PackageManager.PERMISSION_GRANTED
// PERMISSION_GRANTED 同意权限
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){ // ActivityCompat的requestPermissions请求权限
// 第二个参数是一个String数组,我们需要把申请的权限名称放到数组中即可
// 第三个参数是请求码,这个请求码我们在下面权限回调的时候可以用来做判断,判断是那个权限再做相应的操作
ActivityCompat.requestPermissions(MainActivity.this,new String[]{ android.Manifest.permission.CALL_PHONE},1);
}else {
call();
}
接着就是我们打电话的call()方法的操作,以及最后权限请求回来之后的回调方法:
// 防止有异常发生,写在这里
public void call(){
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}catch (SecurityException e){ e.printStackTrace();
}
} //所有的权限回调都是在这里,我们根据requestCode来判断是哪个权限
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 1:
if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
call();
}else {
Toast.makeText(this,"打电话需要权限才能使用",Toast.LENGTH_LONG).show();
}
}
}
访问其他程序中的数据需要-ContentResolver
对于每一个应用程序来说,如果你想要访问内容提供器当中共享的数据,就一定要借助 ContentResolver 类,可以通过Context类当中的getContentResolver()方法来获取该类的实例, ContentResolver 类当中也提供了一系列的方法用于对数据进行CRUD的操作, insert() 添加 update() 更新 delete() 删除 query() 查询
不同于SQLiteDatabase,ContentResolver的CRUD的操作是不接收表名参数的,而是使用一个Uri参数表示。这个参数被称为内容URI,内容URI给内容提供器中的数据表建立了唯一的标识符,它主要是由两部分组成,一部分是 authority,它是用于对不同的应用程序做区分,一般为了避免冲突,都会采取程序包的方式来进行命名, 另一部分是path,path则是相对于同一应用程序中的表走区分的,通常都是添加在authority的后面。当然只有这两部分还是不够的,我们需要在前面加上协议声明,因此标准的形式我们举个例子:
content://com.example.app.provider/table1 当中content://是我们头部的协议 com.example.app.provider是authority /table1就是path
上面我们得到一个URI字符串之后,我们还需要将它解析成Uri对象才能使用,解析的方法也很简单如下:
Uri uri = Uri.parse("content://com.example.app.provider/table1")
有了这个Uri这个对象之后,我们就可以利用它来查询数据了,代码如下:
Cursor cursor = getContentResolver().query(
uri, 指定查询某一个应用下面的某张表
projection, 指定查询的列名
selection, 指定where的约束条件
selectionArgs, 为where中的占位符提供具体的值
sortOrder); 指定查询结果的排序方式
查询完成之后返回的仍然是一个Cursor对象,这时候我们就可以将数据从Cursor对象中逐个读取出来了,
读取的思路仍然是通过移动游标的位置来遍历Cursor的所有行没然后再取出每一个行中国的数据没代码如下:
if(cursor != null){
while(cursor.moveNext()){
String column1 = cursor.getString(cursor.getColumnIndex("column1"));
Int column1 = cursor.getInt(cursor.getColumnIndex("column1"));
}
}
掌握了比较复杂的查询之后,剩下的增加,删除,修改就比较简单了,我们也就不在说了!
我们读取一下联系人
我们这里写一个小demo,来读取一下联系人的信息,然后把它展示在一个ListView当中,具体的代码如下:
public class ContactsActivity extends AppCompatActivity {
//适配器和一个数组,用来存储联系人信息
ArrayAdapter<String> adapter;
List<String> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts);
ListView contactsList = (ListView) findViewById(R.id.contactsListView);
adapter = new ArrayAdapter<String>(ContactsActivity.this, android.R.layout.simple_list_item_1, list);
contactsList.setAdapter(adapter);
// 先检查有没有获取通讯录的权限,要是没有就先请求权限
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.READ_CONTACTS},2);
}else {
readContacts();
}
}
// 获取联系人
private void readContacts(){
Cursor cursor = null;
try{
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
if (cursor != null){
while(cursor.moveToNext()){
// 联系人的名称
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
// 联系人的手机号
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
list.add(displayName+"\n"+number);
}
// 给适配器发消息说数据改变了,这时候会重新刷新一次数据
adapter.notifyDataSetChanged();
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (cursor != null){
cursor.close();
}
}
}
// 获取权限结果
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 2:
if (grantResults.length>0&& grantResults[0] == PackageManager.PERMISSION_GRANTED){
readContacts();
}else {
Toast.makeText(this,"访问通讯录需要权限",Toast.LENGTH_SHORT).show();
}
}
}
}
创建自己的内容提供器
前面也说过,要是想实现跨程序之间的共享数据的功能,官方推荐的就是使用内容提供器,我们可以新建一个类去继承ContentProvider的方式来创建一个自己的内容提供器。ContentProvider里面的6个抽象方法我们全部重写
onCreate()
初始化内容提供器的时候调用,通常会在这里完成数据库的创建和升级操作,返回true表示成功,返回false表示失败,注意的是只有当ContentResolver尝试访问我们的数据库的时候内容提供器才会被初始化
query()
从内容提供器中查询数据,使用uri参数来确定查询哪张表,具体的参数我们就不在说了,前面我们已经说过,查询的具体的结果就在cursor对象中存放返回
insert()
添加数据我们也就不再说了,成功之后会返回一个用于表示这条记录的URI
update()
注意的就一点,受影响的函数将作为返回值返回
delete()
这个和更新一样也是将受影响的行数作为返回值返回
getType()
根据传入的内容URI来返回相应的MIME类型
方法具体的内容我们就不在多说了,可以自己点进类里面去看看。有一点需要注意的就是URI,有一点需要我们注意:
* 表示匹配任意长度的任意字符
# 表示匹配任意长度的数字
所以,我们把一个能够匹配任意表的内容URI可以写成:content://com.example.app.provider/*
我们把一个能够匹配表中任意一行数据的内容URI可以写成:content://com.example.app.provider/table1/#
最后还有一个问题,就是内容URI的匹配问题,有个类UriMatcher类可以了解一下,我们就不在多说了,想想你匹配好了URI,当外面用户进行CRUD操作的时候具体的返回内容就是我们自己自定义的了!以上就是我们要说的关于内容控制器的内容!
Android学习--跨程序共享数据之内容提供其探究的更多相关文章
- android——实现跨程序访问数据
使用之前的SQLite存储的应用程序.首先需要在这个应用程序中创建内容提供器,右击com.example.administrator.exp7包→New→Other→Content Provider, ...
- Android学习笔记(十九)——内容提供器
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整 ...
- 内容提供者(Content Provider)——跨程序共享数据
内容提供者 Content Provider 应用的数据库是不允许其他应用访问的 内容提供者的作用就是让别的应用访问到你的数据库 自定义内容提供者,继承ContentProvider类,重写增删改查方 ...
- 5、Android-跨程序共享数据--内容提供器
Android数据持久化技术:文件存储.SharedPreferences存储.数据库存储 使用这些持久化技术保存的数据只能再当前的应用程序中访问 但是对于不同应用之间的可以实现跨程序数据共享的功能 ...
- android: 实现跨程序数据共享
简单起见,我们还是在上一章中 DatabaseTest 项目的基础上继续开发,通过内容提供器 来给它加入外部访问接口. 打开 DatabaseTest 项目,首先将 MyDatabaseHelper ...
- Android入门(十四)内容提供器-实现跨程序共享实例
原文链接:http://www.orlion.ga/661/ 打开SQLite博文中创建的 DatabaseDemo项目,首先将 MyDatabaseHelper中使用 Toast弹出创建数据库成功的 ...
- 基于Ceph分布式集群实现docker跨主机共享数据卷
上篇文章介绍了如何使用docker部署Ceph分布式存储集群,本篇在此基础之上,介绍如何基于Ceph分布式存储集群实现docker跨主机共享数据卷. 1.环境准备 在原来的环境基础之上,新增一台cen ...
- Android学习笔记之JSON数据解析
转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...
- android学习经常使用的数据文件夹
android工程实践 1.仿360一键清理实现(一) "一键清理"是一个桌面图标,点击图标后,显示一个视图.进行清理动画.之后显示清理了几个进程,释放了多少M内存.点击" ...
随机推荐
- P2127 序列排序
题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格式 输入格式 ...
- LeetCode--Remove Linked List Element
Remove all elements from a linked list of integers that have value val. ExampleGiven: 1 --> 2 --& ...
- 【题解】ZOJ1420 Cashier Employment
论文——冯威<浅析差分约束系统>. 论文讲得很详细,就不解释了.主要想记录一下对于差分约束的理解(感觉以前的学习真的是在囫囵吞枣啊……) 差分约束系统,同于解决线性的不等关系是否存在合法解 ...
- [洛谷P1801]黑匣子_NOI导刊2010提高(06)
题目大意:两个操作:向一个可重集中加入一个元素:询问第$k$大的数($k$为之前询问的个数加一) 题解:离散化,权值线段树直接查询 卡点:无 C++ Code: #include <cstdio ...
- BZOJ day8
好吧,, 补一天题解. 1001 狼抓兔子 妥妥的网络流啊,难度仅次于草地排水,边都给出来了.就是注意反向边也要有流量就行. 1007 水平可见直线 这个题按斜率排序(注意不是绝对值),然后将直线入 ...
- [SCOI2012]喵星球上的点名——堪称十种方法做的题
题意: 给你N个串对,M个询问串,对每个询问串求是多少串对的子串(在串对的某一个中作为子串),以及每个串对最终是包含了多少询问串 方法众多.. 可谓字符串家族八仙过海各显神通. 复杂度不尽相同,O(n ...
- Kd-tree题表
bzoj1941: [Sdoi2010]Hide and Seekbzoj2626: JZPFARbzoj4520: [Cqoi2016]K远点对bzoj2989: 数列bzoj2850: 巧克力王国 ...
- 【BZOJ 1409】 Password 数论(扩展欧拉+矩阵快速幂+快速幂)
读了一下题就会很愉快的发现,这个数列是关于p的幂次的斐波那契数列,很愉快,然后就很愉快的发现可以矩阵快速幂一波,然后再一看数据范围就......然后由于上帝与集合对我的正确启示,我就发现这个东西可以用 ...
- 第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 网络预选赛 A
Problem 1603 - Minimum Sum Time Limit: 2000MS Memory Limit: 65536KB Total Submit: 564 Accepted: ...
- java,jenkins
以前玩的是hudson ,现在玩的是jenkins.以前用的是Tomcat,现在不知道他们怎么不用... 1,装个Jenkins镜像. 2.配置项目: 先取个名字:exchange 配个svn: 构建 ...