文档章节

使用android中ContentProvider组件对外共享以及监听ContentProvider中数据的变化

ht896632
 ht896632
发布于 2016/03/02 14:07
字数 1501
阅读 5
收藏 0
点赞 1
评论 0
1.Contentprovider(组件)内容提供者:
    对外共享数据使用,可以把任意类型的数据进行对外共享;如:xml、数据库、txt等;好处是统一了数据对外的访问方式
    ContentProvider(内容提供者)的scheme已经由Android规定,scheme为:content://主机名(或Authority)用于唯一标识这个
    ContentProvider,外部调用这个可以根据这个标识来找到它。
    路径(Path)可以用来表示我们要操作的数据,路径的应用根据业务而定
    要操作user表中的id为1的记录,可以构建路径:/user/1
    要操作user表中的id为1的记录的age字段,可以构建路径:/user/1/age
    要操作user表中的所有记录,可以构建路径:/user

    如果要操作文件、xml或其它数据,可以这样命名路径:要操作xml文件中user节点下的age字段,可以构建路径:/user/age

使用方法,在使用ContentProvider时首先需要继承ContentProvider,因为ContentProvider是组件需要在应用清单文件中进行配置

示例:

import cn.kafei.service.DBOpenHelper;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class UserProvider extends ContentProvider {
	private DBOpenHelper dbOpenHelper;//打开数据库
	private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);//添加供匹配的URI
	private static final int USERS = 1;
	private static final int USER = 2;
	static {
		// 第一个参数:主机名,也就是在清单文件配置的provider的android:authorities
		// 第二参数:表示要匹配那个路径
		// 第三个参数:表示匹配码的标识,如果匹配成功就返回
		MATCHER.addURI("cn.kafei.provides.userprovider", "user", USERS);//匹配user表中的所有记录
		// #:表示数字,*号表示所有字符
		MATCHER.addURI("cn.kafei.provides.userprovider", "user/#", USER);//根据ID进行匹配
	}

	/**
	 * 当内容提供者的实例被创建出来之后被调用,只执行一次
	 */
	@Override
	public boolean onCreate() {
		dbOpenHelper = new DBOpenHelper(this.getContext());
		return true;
	}

	/**
	 * 返回你目前要操作的数据的内容类型 如:txt:plain/text html:html/text
	 */
	@Override
	public String getType(Uri uri) {
		switch (MATCHER.match(uri)) {
		case 1:
			return "vnd.android.cursor.dir/user";
		case 2:
			return "vnd.android.cursor.item/user";
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
	}

	/**
	 * 可以供外部的应用往内容提供者插入数据 values:用来存放各个字段的值
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		switch (MATCHER.match(uri)) {
		case 1:
			// 如果主键是整型,那么这个行号就等于你的主键值
			long rowid = db.insert("user", "name", values);
			// content://cn.kafei.provides.userprovider/user/1
			// Uri
			// insertUri=Uri.parse("content://cn.kafei.provides.userprovider/user/"+rowid);
			Uri insertUri = ContentUris.withAppendedId(uri, rowid);
			return insertUri;
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
	}

	/**
	 * 允许外部的应用删除内容提供者中的数据
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		int num = 0;
		switch (MATCHER.match(uri)) {
		case 1:
			num = db.delete("user", selection, selectionArgs);
			break;
		case 2:
			long rowid = ContentUris.parseId(uri);// 从URI中获取传入的ID
			String where = "id=" + rowid;
			if (selection != null && !"".equals(selection.trim())) {
				where += " and " + selection;
			}
			num = db.delete("user", where, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
		return num;
	}

	/**
	 * 允许外部的应用对内容提供者中的数据进行更新
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		int num = 0;
		switch (MATCHER.match(uri)) {
		case 1:
			num = db.update("user", values, selection, selectionArgs);
			break;
		case 2:
			long rowid = ContentUris.parseId(uri);// 从URI中提取传入的ID
			String where = "id=" + rowid;
			if (selection != null && !"".equals(selection.trim())) {
				where += " and " + selection;
			}
			num = db.update("user", values, where, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
		return num;
	}

	/**
	 * 可以供外部的应用查询内容提供者的数据
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		switch (MATCHER.match(uri)) {
		case 1:
			return db.query("user", projection, selection, selectionArgs, null,
					null, sortOrder);
		case 2:
			long rowid = ContentUris.parseId(uri);// 从URI中提取传入的ID
			String where = "id=" + rowid;
			if (selection != null && !"".equals(selection.trim())) {
				where += " and " + selection;
			}
			return db.query("user", projection, where, selectionArgs, null,
					null, sortOrder);
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
	}
}
在应用清单文件中(application)标签内进行配置ContentProvider组件:

<!--android:name:表示ContentProvider的类名;android:authorities:表示主机名 ,主机名可以自定义,但是建议按照所提供的格式,以免引起重复-->
        <provider
            android:name=".UserProvider"
            android:authorities="cn.kafei.provides.userprovider" >
        </provider>
以上完成后就算ContentProvider配置完成
测试:

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;

public class AccessContentProviderTest extends AndroidTestCase {
	private final String TAG="AccessContentProviderTest";
	/**
	 * 测试插入
	 */
	public void testInsert()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
		ContentResolver resolver=this.getContext().getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "ht896632");
		values.put("age", "99");
		values.put("amount", "1234000000");
		resolver.insert(uri, values);
	}
	/**
	 * 测试删除
	 */
	public void testDelete()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user/23");
		ContentResolver resolver=this.getContext().getContentResolver();
		resolver.delete(uri, null, null);
	}
	/**
	 * 测试更新
	 */
	public void testUpdate()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user/22");
		ContentResolver resolver=this.getContext().getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "李宏涛");
		
		resolver.update(uri, values, null, null);
	}
	/**
	 * 测试查询
	 */
	public void testQuery()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");
		ContentResolver resolver=this.getContext().getContentResolver();
		Cursor cursor=resolver.query(uri, null, null, null, "id desc");
		while(cursor.moveToNext()){
			String name=cursor.getString(cursor.getColumnIndex("name"));
			int id=cursor.getInt(cursor.getColumnIndex("id"));
			Log.i(TAG, "ID:"+id+" name:"+name);
		}
		cursor.close();
	}
}
注意:ContentProvider的注作用是对外共享数据。

2.监听ContentProvider数据中的变化

思路:首先往ContentProvider中添加数据,然后通过其它应用监听ContentProvider中的数据变化。

添加数据方法(使用一个应用往ContentProvider中添加数据):

public void add(View view){
    	Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
		ContentResolver resolver=this.getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "One");
		values.put("age", "101");
		values.put("amount", "9000");
		resolver.insert(uri, values);
    }
监听数据方法(放在一个应用的onCreate方法中,并且让这个应用保持在运行状态,否则监听不到):

Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
        //第一个参数:要监听的URI
        //第二个参数:是否依赖
        //第三参数:表示监听对象
        this.getContentResolver().registerContentObserver(uri, true, new UserContentOberver(new Handler()));
       //以上代码放在onCreate方法中,监听时,作为监听的应该必须启动 
   /**
     * 监听数据方法
     */
    private class UserContentOberver extends ContentObserver{
		public UserContentOberver(Handler handler) {
			super(handler);
		}
		//只能粗略的监听到数据是否发生变化
    	@Override
    	public void onChange(boolean selfChange) {
    		//select * from user order by id desc limit 1
    		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路径
    		Cursor cursor=getContentResolver().query(uri, null, null, null, "id desc");
    		if(cursor.moveToFirst()){
    			String name=cursor.getString(cursor.getColumnIndex("name"));
    			Log.i(TAG, name);
    		}
    		
    	}
    }
注:ContentProvider、添加数据方法、监听数据方法在三个不同的应用中,连接他们之前的就是一个URI:
content://cn.kafei.provides.userprovider/user

© 著作权归作者所有

共有 人打赏支持
ht896632
粉丝 35
博文 53
码字总数 31361
作品 0
闵行
高级程序员
ContentProvider和Uri详解

问题引出: "/getScrollData" 的使用, public static final Uri INBOXCONTENTURI_SCROLLDATA = Uri .parse("content://" + SMSCONFIGAUTHORITY + "/" + SMSINBOXTABLE_NAME + "/getScrollDa......

eric_zhang
2012/03/23
0
0
[Android] ContentProvider和Uri详解

一、使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过...

枫兮兮
2014/03/03
0
0
android四大组件--ContentProvider详解

一、相关ContentProvider概念解析: 1、ContentProvider简介 在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。但...

大凉龙雀
2015/10/31
0
0
Android ContentProvider详解

1.适用场景 1) ContentProvider为存储和读取数据提供了统一的接口 2) 使用ContentProvider,应用程序可以实现数据共享 3) android内置的许多数据都是使用ContentProvider形式,供开发者调用的...

恰同学少年
2015/07/30
0
0
Content Provider应用实例

Content Provider 属于Android应用程序的组件之一,作为应用程序之间唯一的共享数据的途径,Content Provider 主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的借口。 Androi...

晨曦之光
2012/03/13
0
0
android(4)事务处理,ContentProvider,ListView

一.SQLite数据库 1.事务 beginTransaction(); // 开始事务 setTransactionSuccessful(); // 设置成功点, 在事务结束时, 成功点之前的操作会被提交 endTransaction(); // 结束事务, 通常放在f...

会飞的蝌蚪
2014/03/31
0
0
contentprovider的学习实例总结

工作中遇到了contentprovider数据共享机制,下面来总结一下: 一、ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据...

哈全文
2012/04/19
0
0
Android 的数据存储方式

Android 提供了5种方式存储数据: --使用SharedPreferences存储数据; --文件存储数据; --SQLite数据库存储数据; --使用ContentProvider存储数据; --网络存储数据; 先说下,Preference,...

等待流星
2014/03/13
0
0
关于Android中Contact API的讲解

今日学习任务:实现读取手机中所有联系人的主要信息(名称和联系电话),并以ListView显示 涉及的主要内容:1) Contact API的结构和使用方法 2) ContentProvider组件作用,URI概念及使用方法...

大爱rails
2013/07/04
0
0
[Android] ContentProvider的学习实例总结

一、ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数...

枫兮兮
2014/03/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

pbgo: 基于Protobuf的迷你RPC/REST框架

https://www.oschina.net/p/pbgo

chai2010
13分钟前
0
0
rsync工具介绍、常用选项以及通过ssh同步

linux下的文件同步工具 rsync rsync是非常实用的一个同步工具,可以从a机器到b机器传输一个文件,也可以备份数据,系统默认没有这个工具,要使用命令 yum install -y rsync 安装。 rsync的命...

黄昏残影
28分钟前
0
0
OSChina 周四乱弹 —— 表妹要嫁人 舅妈叮嘱……

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @哈哈哈哈哈嗝:一定要听——The Pancakes的单曲《咁咁咁》 《咁咁咁》- The Pancakes 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :...

小小编辑
今天
66
4
流利阅读笔记30-20180719待学习

重磅:让人类得老年痴呆的竟是它? Lala 2018-07-19 1.今日导读 去年奥斯卡最佳动画长片《寻梦环游记》里有一句经典台词:“比死亡更可怕的,是遗忘”。在电影中,年迈的曾祖母会重复说一样的...

aibinxiao
今天
3
0
1.16 Linux机器相互登录

Linux机器之间以密码方式互相登录 运行命令#ssh [ip address],标准命令:#ssh [username]@ip, 如果没有写用户名,则默认为系统当前登录的用户 命令#w查看系统负载,可查看到连接到该主机的...

小丑鱼00
今天
0
0
about git flow

  昨天元芳做了git分支管理规范的分享,为了拓展大家关于git分支的认知,这里我特意再分享这两个关于git flow的链接,大家可以看一下。 Git 工作流程 Git分支管理策略   git flow本质上是...

qwfys
今天
2
0
Linux系统日志文件

/var/log/messages linux系统总日志 /etc/logrotate.conf 日志切割配置文件 参考https://my.oschina.net/u/2000675/blog/908189 dmesg命令 dmesg’命令显示linux内核的环形缓冲区信息,我们可...

chencheng-linux
今天
1
0
MacOS下给树莓派安装Raspbian系统

下载镜像 前往 树莓派官网 下载镜像。 点击 最新版Raspbian 下载最新版镜像。 下载后请,通过 访达 双击解压,或通过 unzip 命令解压。 检查下载的文件 ls -lh -rw-r--r-- 1 dingdayu s...

dingdayu
今天
1
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
今天
2
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部