一、构造一个自己的Provider实现App之间数据共享

 1、我们先来了解一下   Uri(统一资源定位符) 

  1. 定义:每一个Content Provider使用一个公开的URI唯一标示其数据集,Android所提供的ContentProvider都存放android.provider包中  
  1. 结构:分为ABCD四个部分
  2.  
  3. A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;
  4. BURI 的标识,唯一标识ContentProvider,外部调用者可以根据这个标识来找到它。为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。一般是定义该ContentProvider的包.类的名称
  5. C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;
  6. D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://com.gdnf.provider/tablename/#" #表示数据id。
  7.  
  8. 路径path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
  9. 1、要操作person表中id10的记录,可以构建这样的路径:/person/10
  10. 2、要操作person表中id10的记录的name字段,
  11. person/10/name
  12. 3、要操作person表中的所有记录,可以构建这样的路径:/person
  13. 4、当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
  14. 5、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri
  15. uri
  16. = Uri.parse("content://com.bing.provider.personprovider/person")

 2、UriMatcher

  1. UriMatcher主要用在ContentProvider中,用来构建URI匹配项和判断Uri的正确性,如在insert之前先判断用户传进来的Uri是否与UriMatcher定义的匹配。

 3、ContentUris

  1. Long id=ContentUris.parseId(uri);取出URI中传递的ID
  2. Uri uri=ContentUris.withAppendedId(uri,id);为Uri追加ID

4、案例代码

  1. package com.example.provider;
  2.  
  3. import android.content.ContentProvider;
  4. import android.content.ContentUris;
  5. import android.content.ContentValues;
  6. import android.content.Context;
  7. import android.content.UriMatcher;
  8. import android.database.Cursor;
  9. import android.net.Uri;
  10. import android.support.annotation.Nullable;
  11.  
  12. import com.example.dao.StuDao;
  13.  
  14. /**
  15. * Created by Administrator on 2017/12/18.
  16. */
  17.  
  18. public class StuProvider extends ContentProvider {
  19.  
  20. //定义authorities--这是表示Uri的“B部分”,获取ContentProvider的包名
  21. private static final String authorities="com.example.provider.stuprovider";
  22.  
  23. //构建UriMatcher对象(用于管理和匹配Uri)
  24. private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
  25.  
  26. //为每一个Uri定义一个编码
  27. //所有Stu的编码为1
  28. private static final int STUS=1;
  29. //一个Stu的编码为2
  30. private static final int STU=2;
  31. //根据姓名查找Stu的编码为3
  32. private static final int STU_NAME=3;
  33. //根据性别查找Stu的编码为4
  34. private static final int STU_SEX=4;
  35. //应用UriMatcher对象构建Uri匹配项
  36. static{
  37. //A部分默认为:content:。只需带入B、C、D的值
  38. matcher.addURI(authorities,"/stu",STUS);
  39. matcher.addURI(authorities,"/stu/#",STU);
  40. matcher.addURI(authorities,"/stu/#/name",STU_NAME);
  41. matcher.addURI(authorities,"/stu/#/sex",STU_SEX);
  42. }
  43.  
  44. //声明上下文
  45. private Context context;
  46. @Override
  47. public boolean onCreate() {
  48. context=getContext();
  49. return false;
  50. }
  51.  
  52. @Nullable
  53. @Override
  54. public String getType(Uri uri) {
  55. if(matcher.match(uri)==STUS){
  56. return "vnd.android.cursor.dir/stu";
  57. }else if(matcher.match(uri)==STU){
  58. return "vnd.android.cursor.item/stu";
  59. }
  60. return null;
  61. }
  62.  
  63. @Nullable
  64. @Override
  65. public Uri insert(Uri uri, ContentValues contentValues) {
  66. if(matcher.match(uri)==STUS){
  67. long id=new StuDao(context).addStu(contentValues);//添加学生
  68. Uri newUri=ContentUris.withAppendedId(uri,id);
  69.  
  70. //发生了数据变化,给出一个通知信号
  71. getContext().getContentResolver().notifyChange(uri,null);
  72. return newUri;
  73. }
  74. return null;
  75. }
  76.  
  77. @Override
  78. public int delete(Uri uri, String s, String[] strings) {
  79. StuDao dao=new StuDao(context);
  80. switch (matcher.match(uri)){
  81. case STUS:
  82. dao.delete("tb_stu",null,null);
  83. break;
  84. case STU:
  85. long id=ContentUris.parseId(uri);//从Uri里面解析出Id
  86. dao.delete("tb_stu","_id="+id,null);
  87. break;
  88. }
  89. //发生了数据编号,给出一个通知信号
  90. getContext().getContentResolver().notifyChange(uri,null);
  91. return 0;
  92. }
  93.  
  94. @Override
  95. public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
  96. StuDao dao=new StuDao(context);
  97. int i=-1;
  98. switch (matcher.match(uri)){
  99. case STUS:
  100. i=dao.update("tb_stu",contentValues,s,strings);
  101. break;
  102. case STU:
  103. long id=ContentUris.parseId(uri);//从Uri里面解析出Id
  104. i=dao.update("tb_stu",contentValues,"_id="+id,null);
  105. break;
  106. }
  107. //发生了数据编号,给出一个通知信号
  108. getContext().getContentResolver().notifyChange(uri,null);
  109. return 0;
  110. }
  111.  
  112. @Nullable
  113. @Override
  114. public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
  115. StuDao dao=new StuDao(context);
  116. Cursor cursor=null;
  117. switch (matcher.match(uri)){
  118. case STUS:
  119. cursor=dao.queryStu(strings,s,strings1,null,null,s1,null);
  120. break;
  121. case STU:
  122. long id=ContentUris.parseId(uri);//从Uri里面解析出Id
  123. cursor=dao.queryStu(strings,"_id="+id,null,null,null,s1,null);
  124. break;
  125. }
  126. return cursor;
  127. }
  128. }

二、在另一个程序中如何使用ContentResolver内容解析器进行数据操作

 1、ContentResolver操作ContentProvider中的数据

  1. 当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用getContentResolver()方法获取ContentResolver对象

 2、监听ContentProvider中数据的变化

  1. 如果ContentProvider的访问者需要监听ContentProvider中的数据变化,可以注册一个观察者getContentResolver().registerContentObserver(uri,bool,observer)

 3、数据提供者在数据发生改变时发出消息

  1. getContent().getContentResolver().notifyChange(uri,null)

 4、案例代码

  1. package com.example.android_contentprover_test;
  2.  
  3. import android.app.Activity;
  4. import android.content.ContentProvider;
  5. import android.content.ContentResolver;
  6. import android.content.ContentUris;
  7. import android.content.ContentValues;
  8. import android.database.ContentObserver;
  9. import android.database.Cursor;
  10. import android.net.Uri;
  11. import android.os.Bundle;
  12. import android.os.Handler;
  13. import android.os.Message;
  14. import android.util.Log;
  15. import android.view.View;
  16. import android.widget.Toast;
  17.  
  18. public class MainActivity extends Activity {
  19.  
  20. //定义一个ContentResolver内容解析器
  21. private ContentResolver resolver;
  22. @Override
  23. protected void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. setContentView(R.layout.activity_main);
  26.  
  27. //获取系统的ContentResolver对象
  28. resolver=getContentResolver();
  29. //为resolver添加一个监听事件,监听数据是否发生变化
  30. Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
  31. resolver.registerContentObserver(uri,true,new StuObServer(handler));
  32. }
  33.  
  34. //构建一个handler对象执行数据操作
  35. private Handler handler=new Handler(){
  36. @Override
  37. public void handleMessage(Message msg) {
  38. super.handleMessage(msg);
  39. if(msg.what==1){
  40. //为所欲为
  41. findStuList(null);//执行查询
  42. }
  43. }
  44. };
  45.  
  46. //构建一个观察者类
  47. private class StuObServer extends ContentObserver{
  48.  
  49. private Handler handler;
  50. public StuObServer(Handler handler) {
  51. super(handler);
  52. this.handler=handler;
  53. }
  54. //当发生改变时
  55. @Override
  56. public void onChange(boolean selfChange) {
  57. super.onChange(selfChange);
  58. //监听到数据发生改变时,发出一个编号为1的消息
  59. handler.sendEmptyMessage(1);
  60. }
  61. }
  62.  
  63. public void addStu(View view){
  64. //声明数据来源——路径
  65. Uri addUri=Uri.parse("content://com.example.provider.stuprovider/stu");
  66. //创建一个数据对象
  67. ContentValues values=new ContentValues();
  68. values.put("sname","Join");
  69. values.put("sage",21);
  70. values.put("ssex","男");
  71. //使用内容解析器执行添加(参数为:数据的来源,更改的数据)
  72. Uri newUri=resolver.insert(addUri,values);
  73. //通过解析器得到更改数据的ID
  74. long id= ContentUris.parseId(newUri);
  75. Toast.makeText(this, "添加学生成功,ID="+id, Toast.LENGTH_SHORT).show();
  76.  
  77. //使用内容解析器调用查询方法,查询数据
  78. Cursor cursor=resolver.query(newUri,null,null,null,null);
  79. if(cursor.moveToNext()){
  80. int _id=cursor.getInt(cursor.getColumnIndex("_id"));
  81. String name=cursor.getString(cursor.getColumnIndex("sname"));
  82. Toast.makeText(this, "ID="+_id+",Name="+name, Toast.LENGTH_SHORT).show();
  83. }
  84. cursor.close();
  85. }
  86.  
  87. public void findStuList(View view){
  88. Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
  89. Cursor cursor=resolver.query(uri,null,null,null,null);
  90. while(cursor.moveToNext()){
  91. int _id=cursor.getInt(cursor.getColumnIndex("_id"));
  92. String name=cursor.getString(cursor.getColumnIndex("sname"));
  93. Log.i("App1 StuList", "ID="+_id+",Name="+name);
  94. }
  95. cursor.close();
  96. }
  97. }

Android ContentProvider数据共享的更多相关文章

  1. Android基础 : Android ContentProvider

    Android 应用程序通过ContentProvider实现方式统一的数据共享功能. 外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activi ...

  2. Android--简单开发和使用ContentProvider数据共享

    今天学习的时候学到了ContentProvider数据共享这个东东,所以自己写了个小例子: 我们要开发ContentProvider的话,需要创建一个类去继承ContentProvider,里面会让你 ...

  3. Android ContentProvider基本用法

    转自:https://www.jianshu.com/p/601086916c8f 一.基本概念 ContentProvider是Android系统中提供的专门用户不同应用间进行数据共享的组件,提供了 ...

  4. Android ContentProvider完整案例

    ContentData类,提供数据常量: /** * 提供ContentProvider对外的各种常量,当外部数据需要访问的时候,就可以参考这些常量操作数据. * @author HB * */ pu ...

  5. Android ContentProvider 启动分析

    对于 ContentProvider 还不是很熟悉的同学,可以阅读上一篇 Android ContentProvider 基本原理和使用详解.本文主要是对 contentProvider 的源码进行分 ...

  6. Android ContentProvider和Uri详解 (绝对全面)

        ContentProvider的基本概念 : 1.ContentProvider为存储和读取数据提供了统一的接口 2.使用ContentProvider,应用程序可以实现数据共享 3.andr ...

  7. Android ContentProvider和Uri详解

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

  8. android ContentProvider 笔记

    学习android的contentprovider.笔记记录于此. contentprovider作用是将数据共享给其他的应用. 参考链接 https://www.tutorialspoint.com ...

  9. Android ContentProvider、ContentResolver和ContentObserver的使用

    1.ContentProvider.ContentResolver和ContentObserver ContentProvider是Android的四大组件之中的一个,可见它在Android中的作用非 ...

随机推荐

  1. (转)web前端知识精简

    Web前端技术由 html.css 和 javascript 三大部分构成,是一个庞大而复杂的技术体系,其复杂程度不低于任何一门后端语言.而我们在学习它的时候往往是先从某一个点切入,然后不断地接触和学 ...

  2. workman的学习总结

    我们知道php主要是用来做web应用的,而且平时使用的都是都是和其他的web服务器来结合使用,比如和apache,nginx和apache的时候,是作为apache的一个动态模块来加载,和nginx的 ...

  3. ASP.NET MVC 异常Exception拦截

    一.前言 由于客户端的环境不一致,有可能会造成我们预计不到的异常错误,所以在项目中,友好的异常信息提示,是非常重要的.在asp.net mvc中实现异常属性拦截也非常简单,只需要继承另一个类(Syst ...

  4. Testing - 软件测试知识梳理 - 测试流程

    测试存在于各个阶段: 需求测试--->单元测试--->集成测试--->系统测试--->性能测试--->用户测试--->回归测试 需求测试 完整性&正确性 一 ...

  5. Rolling Hash about the Rsync

    今天看文献看到一个有趣的算法—Rolling Hash,这个算法可以更新在不同的machine上的两个“similar”的文件,也叫做rsync algorithm,rsync顾名思义:remote ...

  6. Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  7. Django model update的各种用法介绍

    Django开发过程中对表(model)的增删改查是最常用的功能之一,本文介绍笔者在使用model update过程中遇到的那些事 model update常规用法 假如我们的表结构是这样的 clas ...

  8. 【xsy1300】 原题的旅行 最短路+倍增

    题目大意:有一个$n$个点,$m$条边的无向图,玩家走过第$i$条边,血槽中的血会下降$v_i$点,如果不足$v_i$点,这人会当场去世. 这$n$个点中,有若干个是关键点,在这些关键点可以将血槽补满 ...

  9. OpenGL10-骨骼动画原理篇(1)

    视频教程请关注 http://edu.csdn.net/lecturer/lecturer_detail?lecturer_id=440 本例程展示如何建立骨骼动画,有些人叫蒙皮动画 定义如下: 当前 ...

  10. Java-jacob-文件转HTML

    Java-jacob-文件转HTML: 下载jacob的jar包,然后举个例子. public static final int WORD_HTML = 8; public static final ...