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

Android 系统为一些常见的数据类型(如音乐、视频、图像、手机通信录联系人信息等)内置了一系列的 Content Provider, 这些都位于android.provider包下。持有特定的许可,可以在自己开发的应用程序中访问这些Content Provider。

让自己的数据和其他应用程序共享有两种方式:创建自己的Content Provier(即继承自ContentProvider的子类) 或者是将自己的数据添加到已有的Content Provider中去,后者需要保证现有的Content Provider和自己的数据类型相同且具有该 Content Provider的写入权限。对于Content Provider,最重要的就是数据模型(data model) 和 URI。

1.数据模型
Content Provider 将其存储的数据以数据表的形式提供给访问者,在数据表中每一行为一条记录,每一列为具有特定类型和意义的数据。每一条数据记录都包括一个 "_ID" 数值字段,改字段唯一标识一条数据。

2.URI
URI,每一个Content Provider 都对外提供一个能够唯一标识自己数据集(data set)的公开URI, 如果一个Content Provider管理多个数据集,其将会为每个数据集分配一个独立的URI。所有的Content Provider 的URI 都以"content://" 开头,其中"content:"是用来标识数据是由Content Provider管理的 schema。

在几乎所有的Content Provider 的操作中都会用到URI,因此一般来讲,如果是自己开发的Content Provider,最好将URI定义为常量,这样在简化开发的同时也提高了代码的可维护性。

首先来介绍如何访问Content Provider中的数据,访问 Content Provider中的数据主要通过ContentResolver对象,ContentResolver类提供了成员方法可以用来对Content Provider 中的数据进行查询、插入、修改和删除等操作。 以查询为例,查询一个 Content Provider 需要掌握如下的信息。

唯一标识Content Provider 的URI
需要访问的数据字段名称。
该数据字段的数据类型

提示: 如果需要访问特定的某条数据记录,只需该记录的ID 即可。

查询Content Provider的方法有两个:ContentResolver的query() 和 Activity 对象的 managedQuery(),二者接收的参数均相同,返回的都是Cursor 对象,唯一不同的是 使用managedQuery 方法可以让Activity 来管理 Cursor 的生命周期。

被管理的Cursor 会在 Activity进入暂停状态的时候调用自己的 deactivate 方法自行卸载,而在Activity回到运行状态时会调用自己的requery 方法重新查询生成的Cursor对象。如果一个未被管理的Cursor对象想被Activity管理,可以调用Activity的 startManagingCursor方法来实现。

Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种多应用间数据共享的方式,比如:联系人信息可以被多个应用程序访问。Content Provider是个实现了一组用于提供其他应用程序存取数据的标准方法的类。

应用程序可以在Content Provider中执行如下操作:
查询数据

修改数据

添加数据

删除数据

/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/MainActivity.java

        
  1. 代码
  2. packagecom.amaker.ch10.app;
  3. importandroid.app.Activity;
  4. importandroid.content.ContentUris;
  5. importandroid.content.ContentValues;
  6. importandroid.database.Cursor;
  7. importandroid.net.Uri;
  8. importandroid.os.Bundle;
  9. importandroid.util.Log;
  10. importcom.amaker.ch10.app.Employees.Employee;
  11. publicclassMainActivityextendsActivity{
  12. @Override
  13. publicvoidonCreate(BundlesavedInstanceState){
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.main);
  16. //添加
  17. insert();
  18. //查询
  19. query();
  20. //更新
  21. update();
  22. //查询
  23. query();
  24. //删除
  25. del();
  26. //查询
  27. query();
  28. }
  29. //删除方法
  30. privatevoiddel(){
  31. //删除ID为1的记录
  32. Uriuri=ContentUris.withAppendedId(Employee.CONTENT_URI,1);
  33. //获得ContentResolver,并删除
  34. getContentResolver().delete(uri,null,null);
  35. }
  36. //更新
  37. privatevoidupdate(){
  38. //更新ID为1的记录
  39. Uriuri=ContentUris.withAppendedId(Employee.CONTENT_URI,1);
  40. ContentValuesvalues=newContentValues();
  41. //添加员工信息
  42. values.put(Employee.NAME,"hz.guo");
  43. values.put(Employee.GENDER,"male");
  44. values.put(Employee.AGE,31);
  45. //获得ContentResolver,并更新
  46. getContentResolver().update(uri,values,null,null);
  47. }
  48. //查询
  49. privatevoidquery(){
  50. //查询列数组
  51. String[]PROJECTION=newString[]{
  52. Employee._ID,//0
  53. Employee.NAME,//1
  54. Employee.GENDER,//2
  55. Employee.AGE//3
  56. };
  57. //查询所有备忘录信息
  58. Cursorc=managedQuery(Employee.CONTENT_URI,PROJECTION,null,
  59. null,Employee.DEFAULT_SORT_ORDER);
  60. //判断游标是否为空
  61. if(c.moveToFirst()){
  62. //遍历游标
  63. for(inti=0;i<c.getCount();i++){
  64. c.moveToPosition(i);
  65. //获得姓名
  66. Stringname=c.getString(1);
  67. Stringgender=c.getString(2);
  68. intage=c.getInt(3);
  69. //输出日志
  70. Log.i("emp",name+":"+gender+":"+age);
  71. }
  72. }
  73. }
  74. //插入
  75. privatevoidinsert(){
  76. //声明Uri
  77. Uriuri=Employee.CONTENT_URI;
  78. //实例化ContentValues
  79. ContentValuesvalues=newContentValues();
  80. //添加员工信息
  81. values.put(Employee.NAME,"amaker");
  82. values.put(Employee.GENDER,"male");
  83. values.put(Employee.AGE,30);
  84. //获得ContentResolver,并插入
  85. getContentResolver().insert(uri,values);
  86. }
  87. }

/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/Employees.java

        
  1. 代码
  2. packagecom.amaker.ch10.app;
  3. importandroid.net.Uri;
  4. importandroid.provider.BaseColumns;
  5. /**
  6. *通讯录常量类
  7. */
  8. publicfinalclassEmployees{
  9. //授权常量
  10. publicstaticfinalStringAUTHORITY="com.amaker.provider.Employees";
  11. privateEmployees(){}
  12. //内部类
  13. publicstaticfinalclassEmployeeimplementsBaseColumns{
  14. //构造方法
  15. privateEmployee(){}
  16. //访问Uri
  17. publicstaticfinalUriCONTENT_URI=Uri.parse("content://"+AUTHORITY+"/employee");
  18. //内容类型
  19. publicstaticfinalStringCONTENT_TYPE="vnd.android.cursor.dir/vnd.amaker.employees";
  20. publicstaticfinalStringCONTENT_ITEM_TYPE="vnd.android.cursor.item/vnd.amaker.employees";
  21. //默认排序常量
  22. publicstaticfinalStringDEFAULT_SORT_ORDER="nameDESC";//按姓名排序
  23. //表字段常量
  24. publicstaticfinalStringNAME="name";//姓名
  25. publicstaticfinalStringGENDER="gender";//性别
  26. publicstaticfinalStringAGE="age";//年龄
  27. }
  28. }

/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/EmployeeProvider.java

        
  1. 代码
  2. packagecom.amaker.ch10.app;
  3. importjava.util.HashMap;
  4. importandroid.content.ContentProvider;
  5. importandroid.content.ContentUris;
  6. importandroid.content.ContentValues;
  7. importandroid.content.UriMatcher;
  8. importandroid.database.Cursor;
  9. importandroid.database.sqlite.SQLiteDatabase;
  10. importandroid.database.sqlite.SQLiteQueryBuilder;
  11. importandroid.net.Uri;
  12. importandroid.text.TextUtils;
  13. importcom.amaker.ch10.app.Employees.Employee;
  14. publicclassEmployeeProviderextendsContentProvider{
  15. //数据库帮助类
  16. privateDBHelperdbHelper;
  17. //Uri工具类
  18. privatestaticfinalUriMatchersUriMatcher;
  19. //查询、更新条件
  20. privatestaticfinalintEMPLOYEE=1;
  21. privatestaticfinalintEMPLOYEE_ID=2;
  22. //查询列集合
  23. privatestaticHashMap<String,String>empProjectionMap;
  24. static{
  25. //Uri匹配工具类
  26. sUriMatcher=newUriMatcher(UriMatcher.NO_MATCH);
  27. sUriMatcher.addURI(Employees.AUTHORITY,"employee",EMPLOYEE);
  28. sUriMatcher.addURI(Employees.AUTHORITY,"employee/#",EMPLOYEE_ID);
  29. //实例化查询列集合
  30. empProjectionMap=newHashMap<String,String>();
  31. //添加查询列
  32. empProjectionMap.put(Employee._ID,Employee._ID);
  33. empProjectionMap.put(Employee.NAME,Employee.NAME);
  34. empProjectionMap.put(Employee.GENDER,Employee.GENDER);
  35. empProjectionMap.put(Employee.AGE,Employee.AGE);
  36. }
  37. //创建是调用
  38. publicbooleanonCreate(){
  39. //实例化数据库帮助类
  40. dbHelper=newDBHelper(getContext());
  41. returntrue;
  42. }
  43. //添加方法
  44. publicUriinsert(Uriuri,ContentValuesvalues){
  45. //获得数据库实例
  46. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  47. //插入数据,返回行ID
  48. longrowId=db.insert(DBHelper.EMPLOYEES_TABLE_NAME,Employee.NAME,values);
  49. //如果插入成功返回uri
  50. if(rowId>0){
  51. UriempUri=ContentUris.withAppendedId(Employee.CONTENT_URI,rowId);
  52. getContext().getContentResolver().notifyChange(empUri,null);
  53. returnempUri;
  54. }
  55. returnnull;
  56. }
  57. //删除方法
  58. publicintdelete(Uriuri,Stringselection,String[]selectionArgs){
  59. //获得数据库实例
  60. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  61. //获得数据库实例
  62. intcount;
  63. switch(sUriMatcher.match(uri)){
  64. //根据指定条件删除
  65. caseEMPLOYEE:
  66. count=db.delete(DBHelper.EMPLOYEES_TABLE_NAME,selection,selectionArgs);
  67. break;
  68. //根据指定条件和ID删除
  69. caseEMPLOYEE_ID:
  70. StringnoteId=uri.getPathSegments().get(1);
  71. count=db.delete(DBHelper.EMPLOYEES_TABLE_NAME,Employee._ID+"="+noteId
  72. +(!TextUtils.isEmpty(selection)?"AND("+selection+')':""),selectionArgs);
  73. break;
  74. default:
  75. thrownewIllegalArgumentException("错误的URI"+uri);
  76. }
  77. getContext().getContentResolver().notifyChange(uri,null);
  78. returncount;
  79. }
  80. //获得类型
  81. publicStringgetType(Uriuri){
  82. returnnull;
  83. }
  84. //查询方法
  85. publicCursorquery(Uriuri,String[]projection,Stringselection,
  86. String[]selectionArgs,StringsortOrder){
  87. SQLiteQueryBuilderqb=newSQLiteQueryBuilder();
  88. switch(sUriMatcher.match(uri)){
  89. //查询所有
  90. caseEMPLOYEE:
  91. qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);
  92. qb.setProjectionMap(empProjectionMap);
  93. break;
  94. //根据ID查询
  95. caseEMPLOYEE_ID:
  96. qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);
  97. qb.setProjectionMap(empProjectionMap);
  98. qb.appendWhere(Employee._ID+"="+uri.getPathSegments().get(1));
  99. break;
  100. default:
  101. thrownewIllegalArgumentException("Uri错误!"+uri);
  102. }
  103. //使用默认排序
  104. StringorderBy;
  105. if(TextUtils.isEmpty(sortOrder)){
  106. orderBy=Employee.DEFAULT_SORT_ORDER;
  107. }else{
  108. orderBy=sortOrder;
  109. }
  110. //获得数据库实例
  111. SQLiteDatabasedb=dbHelper.getReadableDatabase();
  112. //返回游标集合
  113. Cursorc=qb.query(db,projection,selection,selectionArgs,null,null,orderBy);
  114. c.setNotificationUri(getContext().getContentResolver(),uri);
  115. returnc;
  116. }
  117. //更新方法
  118. publicintupdate(Uriuri,ContentValuesvalues,Stringselection,
  119. String[]selectionArgs){
  120. //获得数据库实例
  121. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  122. intcount;
  123. switch(sUriMatcher.match(uri)){
  124. //根据指定条件更新
  125. caseEMPLOYEE:
  126. count=db.update(DBHelper.EMPLOYEES_TABLE_NAME,values,selection,selectionArgs);
  127. break;
  128. //根据指定条件和ID更新
  129. caseEMPLOYEE_ID:
  130. StringnoteId=uri.getPathSegments().get(1);
  131. count=db.update(DBHelper.EMPLOYEES_TABLE_NAME,values,Employee._ID+"="+noteId
  132. +(!TextUtils.isEmpty(selection)?"AND("+selection+')':""),selectionArgs);
  133. break;
  134. default:
  135. thrownewIllegalArgumentException("错误的URI"+uri);
  136. }
  137. getContext().getContentResolver().notifyChange(uri,null);
  138. returncount;
  139. }
  140. }

/Chapter10_ContentProvider_01_Test02/src/com/amaker/ch10/app/DBHelper.java

        
  1. 代码
  2. packagecom.amaker.ch10.app;
  3. importandroid.content.Context;
  4. importandroid.database.sqlite.SQLiteDatabase;
  5. importandroid.database.sqlite.SQLiteOpenHelper;
  6. importcom.amaker.ch10.app.Employees.Employee;
  7. /**
  8. *
  9. *数据库工具类
  10. */
  11. publicclassDBHelperextendsSQLiteOpenHelper{
  12. //数据库名称常量
  13. privatestaticfinalStringDATABASE_NAME="Employees.db";
  14. //数据库版本常量
  15. privatestaticfinalintDATABASE_VERSION=1;
  16. //表名称常量
  17. publicstaticfinalStringEMPLOYEES_TABLE_NAME="employee";
  18. //构造方法
  19. publicDBHelper(Contextcontext){
  20. //创建数据库
  21. super(context,DATABASE_NAME,null,DATABASE_VERSION);
  22. }
  23. //创建时调用
  24. publicvoidonCreate(SQLiteDatabasedb){
  25. db.execSQL("CREATETABLE"+EMPLOYEES_TABLE_NAME+"("
  26. +Employee._ID+"INTEGERPRIMARYKEY,"
  27. +Employee.NAME+"TEXT,"
  28. +Employee.GENDER+"TEXT,"
  29. +Employee.AGE+"INTEGER"
  30. +");");
  31. }
  32. //版本更新时调用
  33. publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){
  34. //删除表
  35. db.execSQL("DROPTABLEIFEXISTSemployee");
  36. onCreate(db);
  37. }
  38. }

/Chapter10_ContentProvider_01_Test02/AndroidManifest.xml

        
  1. 代码
  2. <?xmlversion="1.0"encoding="utf-8"?>
  3. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  4. package="com.amaker.ch10.app"
  5. android:versionCode="1"
  6. android:versionName="1.0">
  7. <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
  8. <providerandroid:name="EmployeeProvider"
  9. android:authorities="com.amaker.provider.Employees"/>
  10. <activityandroid:name=".MainActivity"
  11. android:label="@string/app_name">
  12. <intent-filter>
  13. <actionandroid:name="android.intent.action.MAIN"/>
  14. <categoryandroid:name="android.intent.category.LAUNCHER"/>
  15. </intent-filter>
  16. </activity>
  17. </application>
  18. <uses-sdkandroid:minSdkVersion="3"/>
  19. </manifest>

更多相关文章

  1. 第一行代码读书笔记 Kotlin Android
  2. API Demos 2.2 研读笔记(5)——Window Feature
  3. [Android][Android(安卓)Studio] *.jar 与 *.aar 的生成与*.aar
  4. Android面试题笔记(一)
  5. Android(安卓)proguard混淆编译的问题
  6. [转]Android(安卓)Music和第三方应用
  7. 阅读《Android(安卓)从入门到精通》(3)——Activity 与界面
  8. 译:Android的一些基础问题(一)
  9. Launcher桌面点击&长按&拖动事件处理流程分析

随机推荐

  1. android adb
  2. 跟着做 Android(安卓)NDK学习入门如此简
  3. Android按键添加和处理的方案
  4. Android——编译release版签名系统
  5. android:maxLines和android:ellipsize同
  6. Android——build.prop 解析
  7. android开机启动的问题,android:installLo
  8. android 获取屏幕分辨率
  9. Android的日志系统分层与logcat使用
  10. Android应用程序上传错误The package nam