一、使用ContentProvider共享数据

  当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。以前我们学习过文件的操作模式,通过指定文件的操作模式为Context.MODE_WORLD_READABLE 或Context.MODE_WORLD_WRITEABLE同样可以对外共享数据,但数据的访问方式会因数据存储的方式而不同,如:采用xml文件对外共享数据,需要进行xml解析来读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

  当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并重写下面方法:

  1. package com.example.service;
  2.  
  3. import android.content.ContentProvider;
  4. import android.content.ContentUris;
  5. import android.content.ContentValues;
  6. import android.content.UriMatcher;
  7. import android.database.Cursor;
  8. import android.database.sqlite.SQLiteDatabase;
  9. import android.net.Uri;
  10.  
  11. public class PersonProvider extends ContentProvider {
  12. private DBOpenHelper helper;
  13. // 不匹配返回-1
  14. private static final UriMatcher MATCHER = new UriMatcher(
  15. UriMatcher.NO_MATCH);
  16.  
  17. private static final int PERSONS = 1;// 表示多个
  18. private static final int PERSON = 2; // 表示一条记录
  19. static {
  20. MATCHER.addURI("com.example.providers.personprovider", "person",
  21. PERSONS);
  22. MATCHER.addURI("com.example.providers.personprovider", "person/#",
  23. PERSON);
  24. }
  25.  
  26. // 删除
  27. @Override
  28. public int delete(Uri uri, String selection, String[] selectionArgs) {
  29. SQLiteDatabase db = helper.getWritableDatabase();
  30. int num = 0;
  31. switch (MATCHER.match(uri)) {
  32. case 1:
  33. num = db.delete("person", selection, selectionArgs);
  34. break;
  35. case 2:
  36. long id = ContentUris.parseId(uri);
  37. String where = "id=" + id;
  38. if (selection != null && !"".equals(selection.trim())) {
  39. where += " and " + selection;
  40. }
  41. num = db.delete("person", where, selectionArgs);
  42. break;
  43. default:
  44. throw new IllegalArgumentException("uri参数不正确");
  45. }
  46. return num;
  47. }
  48.  
  49. @Override
  50. public String getType(Uri uri) {
  51. switch (MATCHER.match(uri)) {
  52. case 1:
  53. return "vnd.android.cursor.dir/person";
  54. case 2:
  55. return "vnd.android.cursor.item/person";
  56. default:
  57. throw new IllegalArgumentException("uri参数不正确");
  58. }
  59. }
  60.  
  61. @Override
  62. public Uri insert(Uri uri, ContentValues values) {
  63. SQLiteDatabase db = helper.getWritableDatabase();
  64. switch (MATCHER.match(uri)) {
  65. case 1:
  66. long rowid = db.insert("person", "name", values);
  67. // content://com.example.providers.personprovider/person/1
  68. // Uri insertUri =
  69. // Uri.parse("content://com.example.providers.personprovider/person/"+rowid);
  70. // 在原来的uri后面加上一个rowid
  71. Uri insertUri = ContentUris.withAppendedId(uri, rowid);
  72. return insertUri;
  73.  
  74. default:
  75. throw new IllegalArgumentException("uri参数不正确");
  76. }
  77. }
  78.  
  79. @Override
  80. public boolean onCreate() {
  81. helper = new DBOpenHelper(this.getContext());
  82. return false;
  83. }
  84.  
  85. @Override
  86. public Cursor query(Uri uri, String[] projection, String selection,
  87. String[] selectionArgs, String sortOrder) {
  88. SQLiteDatabase db = helper.getReadableDatabase();
  89. switch (MATCHER.match(uri)) {
  90. case 1:
  91. return db.query("person", projection, selection, selectionArgs,
  92. null, null, sortOrder);
  93. case 2:
  94. long id = ContentUris.parseId(uri);
  95. String where = "id=" + id;
  96. if (selection != null && !"".equals(selection.trim())) {
  97. where += " and " + selection;
  98. }
  99. return db.query("person", projection, where, selectionArgs, null,
  100. null, sortOrder);
  101. default:
  102. throw new IllegalArgumentException("uri参数不正确");
  103. }
  104. }
  105.  
  106. @Override
  107. public int update(Uri uri, ContentValues values, String selection,
  108. String[] selectionArgs) {
  109. SQLiteDatabase db = helper.getWritableDatabase();
  110. int num = 0;
  111. switch (MATCHER.match(uri)) {
  112. case 1:
  113. num = db.update("person", values, selection, selectionArgs);
  114. break;
  115. case 2:
  116. long id = ContentUris.parseId(uri);
  117. String where = "id=" + id;
  118. if (selection != null && !"".equals(selection.trim())) {
  119. where += " and " + selection;
  120. }
  121. num = db.update("person", values, where, selectionArgs);
  122. break;
  123. default:
  124. throw new IllegalArgumentException("uri参数不正确");
  125. }
  126. return num;
  127. }
  128.  
  129. }

  第二步需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider , ContentProvider 采用了authorities(主机名/域名)对它进行唯一标识,你可以把 ContentProvider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名:

  1. <manifest>
  2. <application android:icon="@drawable/icon" android:label="@string/app_name">
  3. <!--
  4.   配置内容提供者:
  5.     name:PersonProvider表示内容提供者类名,包名+类。
  6.     authorities: 内容提供者的唯一标识
  7. -->
  8. <provider android:name="com.example.service.PersonProvider"
  9. android:authorities="com.example.providers.personprovider" >
  10. </provider>
       </application>
  11. </manifest>

二、在另一个应用进行测试上面的代码:

  需要用到ContentResolver和ContentValues两个类,前者封装了内容提供者的增删改查,后者实体类数据。

  1. package com.example.test;
  2.  
  3. import android.content.ContentResolver;
  4. import android.content.ContentValues;
  5. import android.database.Cursor;
  6. import android.net.Uri;
  7. import android.test.AndroidTestCase;
  8. import android.util.Log;
  9.  
  10. public class ContentProviderTest extends AndroidTestCase{
  11.  
  12. public void testInsert(){
  13. Uri uri=Uri.parse("content://com.example.providers.personprovider/person");
  14. ContentResolver resolver = this.getContext().getContentResolver();
  15. ContentValues values = new ContentValues();
  16. values.put("name", "content");
  17. values.put("age", "500");
  18. resolver.insert(uri, values);
  19. }
  20. public void testUpdate(){
  21. Uri uri=Uri.parse("content://com.example.providers.personprovider/person/150");
  22. ContentResolver resolver = this.getContext().getContentResolver();
  23. ContentValues values = new ContentValues();
  24. values.put("name", "provider");
  25. values.put("age", "50");
  26. resolver.update(uri, values, null, null);
  27. }
  28. public void testDelete(){
  29. Uri uri=Uri.parse("content://com.example.providers.personprovider/person/150");
  30. ContentResolver resolver = this.getContext().getContentResolver();
  31. resolver.delete(uri, null, null);
  32. }
  33. public void testQuery(){
  34. Uri uri=Uri.parse("content://com.example.providers.personprovider/person");
  35. ContentResolver resolver = this.getContext().getContentResolver();
  36. Cursor cursor = resolver.query(uri, null, null, null, null);
  37. while (cursor.moveToNext()) {
  38. String name = cursor.getString(cursor.getColumnIndex("name"));
  39. int age = cursor.getInt(cursor.getColumnIndex("age"));
  40. Log.i("ContentProviderTest", " "+name+" : "+age);
  41. }
  42. }
  43. }

三、Uri介绍

  Uri代表了要操作的数据,Uri主要包含了两部分信息:1》需要操作的ContentProvider ,2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:

content://com.example.providers.personprovider/person/10,其中“com.example.providers.personprovider”指主机名或authority,“person/10”表示路径。

  1. ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://
  2.  
  3. 主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
  4.  
  5. 路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
  6.  
  7. 要操作person表中id10的记录,可以构建这样的路径:/person/10
  8.  
  9. 要操作person表中id10的记录的name字段, person/10/name
  10.  
  11. 要操作person表中的所有记录,可以构建这样的路径:/person
  12.  
  13. 要操作xxx表中的记录,可以构建这样的路径:/xxx
  14.  
  15. 当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
  16.  
  17. 要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
  18.  
  19. 如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
  20.  
  21. Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

 四、监听内容提供者的数据变化:

  1、对提供内容提供者的应用加入改变通知:

  1. package cn.itcast.db;
  2.  
  3. import cn.itcast.service.DBOpenHelper;
  4. import android.content.ContentProvider;
  5. import android.content.ContentUris;
  6. import android.content.ContentValues;
  7. import android.content.UriMatcher;
  8. import android.database.Cursor;
  9. import android.database.sqlite.SQLiteDatabase;
  10. import android.net.Uri;
  11.  
  12. public class PersonContentProvider extends ContentProvider {
  13. private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
  14. private static final int PERSONS = 1;
  15. private static final int PERSON = 2;
  16. private DBOpenHelper dbOpenHelper;
  17. static{
  18. matcher.addURI("cn.itcast.providers.personprovider", "person", PERSONS);
  19. matcher.addURI("cn.itcast.providers.personprovider", "person/#", PERSON);
  20. }
  21.  
  22. @Override
  23. public boolean onCreate() {
  24. dbOpenHelper = new DBOpenHelper(this.getContext());
  25. return true;
  26. }
  27.  
  28. @Override
  29. public int delete(Uri uri, String selection, String[] selectionArgs) {
  30. SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
  31. int num = 0 ;//已经删除的记录数量
  32. switch (matcher.match(uri)) {
  33. case PERSONS:
  34. num = db.delete("person", selection, selectionArgs);
  35. break;
  36. case PERSON:
  37. long id = ContentUris.parseId(uri);
  38. String where = "personid="+ id;
  39. if(selection!=null && !"".equals(selection)){ // personid=12 and name=?
  40. where = where + " and "+ selection;
  41. }
  42. num = db.delete("person", where, selectionArgs);
  43. break;
  44. default:
  45. throw new IllegalArgumentException("Unkown Uri:"+ uri);
  46. }
  47. getContext().getContentResolver().notifyChange(uri, null);
  48. return num;
  49. }
  50.  
  51. @Override
  52. public String getType(Uri uri) {//返回当前操作的数据类型
  53. switch (matcher.match(uri)) {
  54. case PERSONS://操作的是集合类型数据
  55. return "vnd.android.cursor.dir/person";
  56. case PERSON:
  57. return "vnd.android.cursor.item/person";
  58. default:
  59. throw new IllegalArgumentException("Unkown Uri:"+ uri);
  60. }
  61. }
  62.  
  63. @Override
  64. public Uri insert(Uri uri, ContentValues values) {
  65. SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
  66. long id = 0 ;
  67. switch (matcher.match(uri)) {
  68. case PERSONS:
  69. id = db.insert("person", "personid", values);//得到记录的id
  70. getContext().getContentResolver().notifyChange(uri, null);
  71. return ContentUris.withAppendedId(uri, id);//返回代表新增记录的Uri
  72. case PERSON:
  73. id = db.insert("person", "personid", values);//得到记录的id
  74. String strUri = uri.toString();
  75. Uri personUri = Uri.parse(strUri.substring(0, strUri.lastIndexOf("/")));
  76. getContext().getContentResolver().notifyChange(personUri, null);
  77. return ContentUris.withAppendedId(personUri, id);
  78. default:
  79. throw new IllegalArgumentException("Unkown Uri:"+ uri);
  80. }
  81. }
  82.  
  83. @Override
  84. public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
  85. SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
  86. switch (matcher.match(uri)) {
  87. case PERSONS:
  88. return db.query("person", projection, selection, selectionArgs, null, null, sortOrder);
  89.  
  90. case PERSON:
  91. long id = ContentUris.parseId(uri);
  92. String where = "personid="+ id;
  93. if(selection!=null && !"".equals(selection)){ // personid=12 and name=?
  94. where = where + " and "+ selection;
  95. }
  96. return db.query("person", projection, where, selectionArgs, null, null, sortOrder);
  97.  
  98. default:
  99. throw new IllegalArgumentException("Unkown Uri:"+ uri);
  100. }
  101. }
  102.  
  103. @Override
  104. public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
  105. SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
  106. int num = 0 ;//已经修改的记录数量
  107. switch (matcher.match(uri)) {
  108. case PERSONS:
  109. num = db.update("person", values, selection, selectionArgs);
  110. break;
  111. case PERSON:
  112. long id = ContentUris.parseId(uri);
  113. String where = "personid="+ id;
  114. if(selection!=null && !"".equals(selection)){
  115. where = where + " and "+ selection;
  116. }
  117. num = db.update("person", values, where, selectionArgs);
  118. break;
  119. default:
  120. throw new IllegalArgumentException("Unkown Uri:"+ uri);
  121. }
  122. getContext().getContentResolver().notifyChange(uri, null);//通知数据发生变化
  123. return num;
  124. }
  125.  
  126. }

  2、注册要通知改变的uri,启动B应用:

  3、执行添加方法:

Android学习笔记_10_ContentProvider内容提供者的使用的更多相关文章

  1. 【转】Pro Android学习笔记(七):了解Content Provider(下上)

    我们通过一个Content Provider小例子进行详细说明.数据源是一个SQLite数据库,名字为books.db,该数据库只含有一个表格,名字为books.表格中含有name,isbn,auth ...

  2. 【转】Pro Android学习笔记(五):了解Content Provider(上)

    Content Provider是抽象数据封装和数据访问机制,例如SQLite是Android设备带有的数据源,可以封装到一个content provider中.要通过content provider ...

  3. Android 学习笔记之Volley(七)实现Json数据加载和解析...

    学习内容: 1.使用Volley实现异步加载Json数据...   Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...

  4. Android组件系列----ContentProvider内容提供者

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  5. Android学习笔记之JSON数据解析

    转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...

  6. udacity android 学习笔记: lesson 4 part b

    udacity android 学习笔记: lesson 4 part b 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 ...

  7. Android学习笔记36:使用SQLite方式存储数据

    在Android中一共提供了5种数据存储方式,分别为: (1)Files:通过FileInputStream和FileOutputStream对文件进行操作.具体使用方法可以参阅博文<Andro ...

  8. Pro Android学习笔记 ActionBar(1):Home图标区

     Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...

  9. 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET

    目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...

随机推荐

  1. word 快捷键

    Ctrl+shift+F9  清除word文档中的超链接

  2. 02-使用注解配置spring

    1 准备工作 1.导包 4+2+spring-aop[新版本需要导入 spring-aop 包] 2.为主配置文件引入新的命名空间(约束) [context] 3.开启使用注解代理配置文件 4.在类中 ...

  3. TOJ 1023 Taxi Cab Scheme

    Description Running a taxi station is not all that simple. Apart from the obvious demand for a centr ...

  4. FZU 2216——The Longest Straight——————【二分、枚举】

    Problem 2216 The Longest Straight Accept: 17    Submit: 39Time Limit: 1000 mSec    Memory Limit : 32 ...

  5. 【linux相识相知】独立硬盘冗余阵列-RAID

    独立硬盘冗余阵列(RAID,Redundant Array of Independant Disks),旧称为廉价磁盘冗余阵列(Redundant Array of Inexpensive Disks ...

  6. 在浏览器中对访问的网页中的cookie添加和修改

    做权限相关的东西,使用到了cookie,关于它的安全性,cookie在浏览器中,通过插件是可以对其进行修改的,如下: 1.FireFox 安装Edit This Cookie 插件,之后点击插件图标即 ...

  7. 虚拟环境--pipenv

    1.安装pipenv,这个工具属于python3 升级pip : pip3 install pipenv 2.在项目中创建虚拟环境 3.激活虚拟环境,进入虚拟环境 进入虚拟环境之前: pipenv s ...

  8. Trim a Binary Search Tree

    Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that a ...

  9. python高阶函数sorted

    原文 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因 ...

  10. Jquery系列:textarea常用操作

    1.textarea内容的读取与设置 读textarea文本值可以用name和id.而写入文本值只能用id. <textarea name="content" id=&quo ...