Android ContentProvider数据共享
一、构造一个自己的Provider实现App之间数据共享
1、我们先来了解一下 Uri(统一资源定位符)
定义:每一个Content Provider使用一个公开的URI唯一标示其数据集,Android所提供的ContentProvider都存放android.provider包中
结构:分为A、B、C、D四个部分 A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;
B:URI 的标识,唯一标识ContentProvider,外部调用者可以根据这个标识来找到它。为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。一般是定义该ContentProvider的包.类的名称
C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://com.gdnf.provider/tablename/#" #表示数据id。 路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
1、要操作person表中id为10的记录,可以构建这样的路径:/person/10
2、要操作person表中id为10的记录的name字段,
person/10/name
3、要操作person表中的所有记录,可以构建这样的路径:/person
4、当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
5、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri
uri
= Uri.parse("content://com.bing.provider.personprovider/person")
2、UriMatcher
UriMatcher主要用在ContentProvider中,用来构建URI匹配项和判断Uri的正确性,如在insert之前先判断用户传进来的Uri是否与UriMatcher定义的匹配。
3、ContentUris
Long id=ContentUris.parseId(uri);取出URI中传递的ID
Uri uri=ContentUris.withAppendedId(uri,id);为Uri追加ID
4、案例代码
package com.example.provider; import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.Nullable; import com.example.dao.StuDao; /**
* Created by Administrator on 2017/12/18.
*/ public class StuProvider extends ContentProvider { //定义authorities--这是表示Uri的“B部分”,获取ContentProvider的包名
private static final String authorities="com.example.provider.stuprovider"; //构建UriMatcher对象(用于管理和匹配Uri)
private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH); //为每一个Uri定义一个编码
//所有Stu的编码为1
private static final int STUS=1;
//一个Stu的编码为2
private static final int STU=2;
//根据姓名查找Stu的编码为3
private static final int STU_NAME=3;
//根据性别查找Stu的编码为4
private static final int STU_SEX=4;
//应用UriMatcher对象构建Uri匹配项
static{
//A部分默认为:content:。只需带入B、C、D的值
matcher.addURI(authorities,"/stu",STUS);
matcher.addURI(authorities,"/stu/#",STU);
matcher.addURI(authorities,"/stu/#/name",STU_NAME);
matcher.addURI(authorities,"/stu/#/sex",STU_SEX);
} //声明上下文
private Context context;
@Override
public boolean onCreate() {
context=getContext();
return false;
} @Nullable
@Override
public String getType(Uri uri) {
if(matcher.match(uri)==STUS){
return "vnd.android.cursor.dir/stu";
}else if(matcher.match(uri)==STU){
return "vnd.android.cursor.item/stu";
}
return null;
} @Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
if(matcher.match(uri)==STUS){
long id=new StuDao(context).addStu(contentValues);//添加学生
Uri newUri=ContentUris.withAppendedId(uri,id); //发生了数据变化,给出一个通知信号
getContext().getContentResolver().notifyChange(uri,null);
return newUri;
}
return null;
} @Override
public int delete(Uri uri, String s, String[] strings) {
StuDao dao=new StuDao(context);
switch (matcher.match(uri)){
case STUS:
dao.delete("tb_stu",null,null);
break;
case STU:
long id=ContentUris.parseId(uri);//从Uri里面解析出Id
dao.delete("tb_stu","_id="+id,null);
break;
}
//发生了数据编号,给出一个通知信号
getContext().getContentResolver().notifyChange(uri,null);
return 0;
} @Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
StuDao dao=new StuDao(context);
int i=-1;
switch (matcher.match(uri)){
case STUS:
i=dao.update("tb_stu",contentValues,s,strings);
break;
case STU:
long id=ContentUris.parseId(uri);//从Uri里面解析出Id
i=dao.update("tb_stu",contentValues,"_id="+id,null);
break;
}
//发生了数据编号,给出一个通知信号
getContext().getContentResolver().notifyChange(uri,null);
return 0;
} @Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
StuDao dao=new StuDao(context);
Cursor cursor=null;
switch (matcher.match(uri)){
case STUS:
cursor=dao.queryStu(strings,s,strings1,null,null,s1,null);
break;
case STU:
long id=ContentUris.parseId(uri);//从Uri里面解析出Id
cursor=dao.queryStu(strings,"_id="+id,null,null,null,s1,null);
break;
}
return cursor;
}
}
二、在另一个程序中如何使用ContentResolver内容解析器进行数据操作
1、ContentResolver操作ContentProvider中的数据
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用getContentResolver()方法获取ContentResolver对象
2、监听ContentProvider中数据的变化
如果ContentProvider的访问者需要监听ContentProvider中的数据变化,可以注册一个观察者getContentResolver().registerContentObserver(uri,bool,observer)
3、数据提供者在数据发生改变时发出消息
getContent().getContentResolver().notifyChange(uri,null)
4、案例代码
package com.example.android_contentprover_test; import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast; public class MainActivity extends Activity { //定义一个ContentResolver内容解析器
private ContentResolver resolver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //获取系统的ContentResolver对象
resolver=getContentResolver();
//为resolver添加一个监听事件,监听数据是否发生变化
Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
resolver.registerContentObserver(uri,true,new StuObServer(handler));
} //构建一个handler对象执行数据操作
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==1){
//为所欲为
findStuList(null);//执行查询
}
}
}; //构建一个观察者类
private class StuObServer extends ContentObserver{ private Handler handler;
public StuObServer(Handler handler) {
super(handler);
this.handler=handler;
}
//当发生改变时
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//监听到数据发生改变时,发出一个编号为1的消息
handler.sendEmptyMessage(1);
}
} public void addStu(View view){
//声明数据来源——路径
Uri addUri=Uri.parse("content://com.example.provider.stuprovider/stu");
//创建一个数据对象
ContentValues values=new ContentValues();
values.put("sname","Join");
values.put("sage",21);
values.put("ssex","男");
//使用内容解析器执行添加(参数为:数据的来源,更改的数据)
Uri newUri=resolver.insert(addUri,values);
//通过解析器得到更改数据的ID
long id= ContentUris.parseId(newUri);
Toast.makeText(this, "添加学生成功,ID="+id, Toast.LENGTH_SHORT).show(); //使用内容解析器调用查询方法,查询数据
Cursor cursor=resolver.query(newUri,null,null,null,null);
if(cursor.moveToNext()){
int _id=cursor.getInt(cursor.getColumnIndex("_id"));
String name=cursor.getString(cursor.getColumnIndex("sname"));
Toast.makeText(this, "ID="+_id+",Name="+name, Toast.LENGTH_SHORT).show();
}
cursor.close();
} public void findStuList(View view){
Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
Cursor cursor=resolver.query(uri,null,null,null,null);
while(cursor.moveToNext()){
int _id=cursor.getInt(cursor.getColumnIndex("_id"));
String name=cursor.getString(cursor.getColumnIndex("sname"));
Log.i("App1 StuList", "ID="+_id+",Name="+name);
}
cursor.close();
}
}
Android ContentProvider数据共享的更多相关文章
- Android基础 : Android ContentProvider
Android 应用程序通过ContentProvider实现方式统一的数据共享功能. 外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activi ...
- Android--简单开发和使用ContentProvider数据共享
今天学习的时候学到了ContentProvider数据共享这个东东,所以自己写了个小例子: 我们要开发ContentProvider的话,需要创建一个类去继承ContentProvider,里面会让你 ...
- Android ContentProvider基本用法
转自:https://www.jianshu.com/p/601086916c8f 一.基本概念 ContentProvider是Android系统中提供的专门用户不同应用间进行数据共享的组件,提供了 ...
- Android ContentProvider完整案例
ContentData类,提供数据常量: /** * 提供ContentProvider对外的各种常量,当外部数据需要访问的时候,就可以参考这些常量操作数据. * @author HB * */ pu ...
- Android ContentProvider 启动分析
对于 ContentProvider 还不是很熟悉的同学,可以阅读上一篇 Android ContentProvider 基本原理和使用详解.本文主要是对 contentProvider 的源码进行分 ...
- Android ContentProvider和Uri详解 (绝对全面)
ContentProvider的基本概念 : 1.ContentProvider为存储和读取数据提供了统一的接口 2.使用ContentProvider,应用程序可以实现数据共享 3.andr ...
- Android ContentProvider和Uri详解
一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据, 也就是说你可以通过ContentProvider把应用中的数据共享 ...
- android ContentProvider 笔记
学习android的contentprovider.笔记记录于此. contentprovider作用是将数据共享给其他的应用. 参考链接 https://www.tutorialspoint.com ...
- Android ContentProvider、ContentResolver和ContentObserver的使用
1.ContentProvider.ContentResolver和ContentObserver ContentProvider是Android的四大组件之中的一个,可见它在Android中的作用非 ...
随机推荐
- ESP-IDF版本2.1.1
版本2.1.1是一个错误修复版本.它包括对KRACK和BlueBorne漏洞的修复. 版本2.1.1的文档可在http://esp-idf.readthedocs.io/en/v2.1.1/上找到. ...
- 将Linux(ubuntu)安装到U盘上,实现即插即用
说明: 本教程是说明如何将ubuntu系统安装到U盘上(也就是把U盘当做电脑的硬盘),可以实现U盘插到任何电脑上都能够在实体机上运行ubuntu系统,而且所有的运行配置都能被保存,相当于随身携带的一个 ...
- 生成多个git ssh密钥
如果你已经有了一套名为 id_rsa 的公秘钥,将要生成另外一个公钥,比如 aysee ,你也可以使用任何你喜欢的名字. 步骤如下: 1.生成一个新的自定义名称的公钥: ssh-keygen -t r ...
- Swift5 语言指南(五) 基本运算符
一个运营商是一个特殊的符号,或者你使用来检查,更改或合并值的短语.例如,加法运算符(+)添加两个数字,如,和逻辑AND运算符()组合两个布尔值,如.let i = 1 + 2&&if ...
- OpenStack-Ocata版+CentOS7.6 云平台环境搭建 —7.网络服务Neutron配置
网络服务Neutron本章节结束如何安装并配置网络服务(neutron)采用:ref:`provider networks <network1>`或:ref:`self-service n ...
- Qt之使用CQU库快速开发统一风格界面
在使用Qt开发时,肯定是想让开发的项目界面统一风格:不希望每个界面都要程序员用代码去修饰美化以及进行事件处理等等,这样非常繁琐,容易出错而且没有格调:所以我就开发一个动态链接库,封装统一的风格界面.事 ...
- Linux 后台运行命令:nohup 和 &
[参开文章]:nohup 与 & 的区别 1. nohup 1.1 基本概念 将程序以忽略挂起信号的方式运行起来: 不可以免疫 Ctrl + C 的 SIGINT 中断信号: 可以免疫 SI ...
- Win10下音频设备无法播放音乐问题定位
最近一直在调试音频设备,由于音频设备需要在不同的采样率下面转换,所以会经常导致我的win10无法播放和录音. 刚开始在网上搜了相关的知识,但是一直没找到有效的解决方案.后来,无奈之下,使用了微软的声音 ...
- 干货:教你如何监控 Java 线程池运行状态
之前写过一篇 Java 线程池的使用介绍文章<线程池全面解析>,全面介绍了什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中, ...
- 11.10 vue
https://vuejs.org/js/vue.js ide typora v-pre 指令 vuex text script . 语法 BCF 终端输入 node -v npm -v 包管理 ...