一、Content Provider基本概念 

1、ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。

2、使用ContentProvider可以在不同的应用程序之间共享数据。

3、Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。

ContentProvider所提供的函数:

query(),insert(),update(),delete(),getType(),onCreate()等。

二、URI(统一资源标识符)的使用方法

为系统的每一个资源给其一个名字,比方说通话记录。

1、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。

2、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分:

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"

B:URI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称;"content://hx.android.text.myprovider"

C:路径,不知道是不是路径,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就ok了;"content://hx.android.text.myprovider/tablename"

D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;"content://hx.android.text.myprovider/tablename/#" #表示数据id

三、ContentProvider的实现过程

自己实现ContentProvider不常见,因为可能不需要和别的应用程序交换数据。使用内置的ContentProvider比较多。

1、定义一个CONTENT_URI常量,提供了访问ContentProvider的标识符。

 public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transportationprovider"); 

其中:content是协议

Com.exmaple.codelab.transportationprovider是类名,包含完整的包名。

Uri.parse将一个字符串转换成Uri类型。

如果Provider包含子表,同样定义包含字表的CONTENT_URI。

 content://com.example.codelab.transportationprovider/train  
 content://com.example.codelab.transportationprovider/air/domestic  
 content://com.example.codelab.transportationprovider/air/international 

然后定义列,确保里面包含一个_id的列。

2、定义一个类,继承ContentProvider。

public class FirstContentProvider extends ContentProvider

先介绍一下ContentProvider用到的UriMatcher。UriMatcher的一个重要的函数是match(Uri uri)。这个函数可以匹配Uri,根据传入的不同Uri返回不同的自定义整形值,以表明Uri访问的不同资源的类型。

例如:

       public static final UriMatcher uriMatcher;   
       static {   
                      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);   
                      uriMatcher.addURI(Book.AUTHORITY, "item", Book.ITEM);   
                      uriMatcher.addURI(Book.AUTHORITY, "item/#", Book.ITEM_ID);   
               }  

这里UriMatcher类型的静态字段是用来匹配传入到ContentProvider中的Uri的类。其构造方法传入的匹配码是使用match()方法匹配根路径时返回的值,这个匹配码可以为一个大于零的数表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径。addURI()方法是用来增加其他URI匹配路径的,第一个参数传入标识ContentProvider的AUTHORITY字符串。第二个参数传入需要匹配的路径,这里的#号为通配符,代表匹配任意数字,另外还可以用*来匹配任意文本。第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI返回相对应的匹配码。 例如:sMatcher.addURI(“com.test.provider.personprovider”, “person”, 1);如果match()方法匹配content://com.test.provider.personprovider/person路径,返回匹配码为1。

3、实现query,insert,update,delete,getType和onCreate方法。

4、在AndroidManifest.xml当中进行声明。

 <!-- android:name是完成ContentProvider类的全称 
              android:authorities是和FirstProvidermetaData中的常量AUTHORITY的值一样,否则会报错 
          --> 
         <provider android:name="com.bj.FirstContentProvider" 
             android:authorities="com.bj.firstcontentprovider" 
             /> 

四、具体代码

Activity19Activity.java

publicclassActivity19ActivityextendsActivity {

privateButtonqueryButton= null;

privateButtoninsertButton= null;

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

queryButton= (Button)this.findViewById(R.id.query);

queryButton.setOnClickListener(newQueryListener());

insertButton= (Button)this.findViewById(R.id.insert);

insertButton.setOnClickListener(newInsertListener());

System.out.println(getContentResolver().getType(FirstProvidermetaData.UserTableMetaData.CONTENT_URI));

}

classInsertListenerimplementsOnClickListener {

@Override

publicvoidonClick(View v) {

//TODOAuto-generated method stub

ContentValues values =newContentValues();

values.put(FirstProvidermetaData.UserTableMetaData.USER_NAME,

"michal");

Uri uri = getContentResolver()

.insert(

FirstProvidermetaData.UserTableMetaData.CONTENT_URI,

values);

System.out.println("uri--->"+ uri.toString());

}

}

classQueryListenerimplementsOnClickListener {

publicvoidonClick(View v) {

Cursor c = getContentResolver().query(

FirstProvidermetaData.UserTableMetaData.CONTENT_URI,null,

null,null,null);

while(c.moveToNext()) {

System.out.println(c.getString(c.getColumnIndex("username")));

}

}

}

}

FirstContentProvider.java

publicclassFirstContentProviderextendsContentProvider {

//当别的程序来访问这个ContentProvider,是通过Uri来访问的,UriMatcher检查是否符合标准

    //给uri起一个规则,返回数字

publicstaticfinalUriMatcheruriMatcher;

//下面定义两个规则

publicstaticfinal intINCOMING_USER_COLLECTION= 1;

publicstaticfinal intINCOMING_USER_SINGLE= 2;

privateDatabaseHelperdh;

static{//下面的users前面不能加/

uriMatcher=newUriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI(FirstProvidermetaData.AUTHORITY,"users",

INCOMING_USER_COLLECTION);

uriMatcher.addURI(FirstProvidermetaData.AUTHORITY,"users/#",

INCOMING_USER_SINGLE);

}

//有点类似于sql里面表的别名,这个也是给列其别名,必须要用

    //列的别名还是原来的名,没必要修改

publicstaticHashMap<String,String>userProjectionMap;

static{

userProjectionMap=newHashMap<String,String>();

userProjectionMap.put(UserTableMetaData._ID, UserTableMetaData._ID);

userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);

}

@Override

publicintdelete(Uri uri, String selection, String[] selectionArgs) {

//TODOAuto-generated method stub

System.out.println("delete");

return0;

}

//根据传入的URI,返回该URI所表示的数据类型

    //也就是说,我们通过URI要访问的数据,返回什么类型

@Override

publicString getType(Uri uri) {

//TODOAuto-generated method stub

System.out.println("getType");

switch(uriMatcher.match(uri)) {

caseINCOMING_USER_COLLECTION:

// UserTableMetaData是FirstProvidermetaData的内部类

returnUserTableMetaData.CONTENT_TYPE;

caseINCOMING_USER_SINGLE:

returnUserTableMetaData.CONTENT_TYPE_ITEM;

default:

thrownewIllegalArgumentException("Unknown uri"+ uri);

}

}

@Override

publicUri insert(Uri uri, ContentValues values) {

//TODOAuto-generated method stub

System.out.println("insert");

SQLiteDatabase db =dh.getWritableDatabase();

//返回表中自动增长的列的值,否则返回-1  

longrowId = db.insert(UserTableMetaData.TABLE_NAME,null, values);

if(rowId>0){

//将rowId追加到后面

           //contentUris:用来处理Uri的工具类

Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);

//通知监听器,数据已经改变

getContext().getContentResolver().notifyChange(insertedUserUri,null);

returninsertedUserUri;

}

thrownewSQLException("Failed to insert row into "+uri);

}

//是一个回调方法,所以说在ContentProvider创建的时候执行

    //也就是创建这个DatabaseHelper对象

@Override

publicbooleanonCreate() {

//TODOAuto-generated method stub

//getContext得到当前正在运行着的context

dh= newDatabaseHelper(getContext(),FirstProvidermetaData.DATABASE_NAME);

System.out.println("on create");

SQLiteDatabasedb = dh.getReadableDatabase();

returntrue;

}

//projection:查询的列有哪些

    //selection:where子句的内容,可以用?

    //selectionArgs:占位符对应的参数

    //sortOrder:排序

@Override

publicCursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

//TODOAuto-generated method stub

System.out.println("query");

//创建一个查询的语句

SQLiteQueryBuilder qb =newSQLiteQueryBuilder();

switch(uriMatcher.match(uri)){

caseINCOMING_USER_COLLECTION:

//设置查询哪张表

qb.setTables(UserTableMetaData.TABLE_NAME);

qb.setProjectionMap(userProjectionMap);

break;

caseINCOMING_USER_SINGLE:

qb.setTables(UserTableMetaData.TABLE_NAME);

qb.setProjectionMap(userProjectionMap);

//添加where条件,getPathSegments:得到uri的path部分content:XXX/user/1,get(1)得到1

qb.appendWhere(UserTableMetaData._ID+"="+uri.getPathSegments().get(1));

break;

}

String orderBy;

if(TextUtils.isEmpty(sortOrder)){

orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;

}

else

{

orderBy = sortOrder;

}

SQLiteDatabase db =dh.getWritableDatabase();

//下面的query使用qb这个对象

Cursor c = qb.query(db, projection, selection, selectionArgs,null,null, orderBy);

//也是通知下

c.setNotificationUri(getContext().getContentResolver(), uri);

System.out.println("query");

returnc;

}

@Override

publicintupdate(Uri uri, ContentValues values, String selection,

String[] selectionArgs) {

//TODOAuto-generated method stub

return0;

}

}

FirstProvidermetaData.java

publicclassFirstProvidermetaData {

publicstaticfinalString AUTHORITY="com.bj.firstcontentprovider";//继承了contentprovider的类的全名

    //数据库名称 

publicstaticfinalString DATABASE_NAME="FirstProvider.db";

//数据库的版本

publicstaticfinal intDATABASE_VERSION= 1;

//表名  

publicstaticfinalString USERS_TABLE_NAME="users";

publicstaticfinal classUserTableMetaDataimplementsBaseColumns{

//表名

publicstaticfinalString TABLE_NAME="users";

//访问该ContentProvider的URI

publicstaticfinalUri CONTENT_URI=Uri.parse("content://"+AUTHORITY+"/users");

publicstaticfinalString CONTENT_TYPE="vnd.android.cursor.dir/vnd.firstprovider.user";

publicstaticfinalString CONTENT_TYPE_ITEM="vnd.android.cursor.item/vnd.firstprovider.user";

//列名,在users表中添加一个名为name的列

publicstaticfinalString USER_NAME="name";

//默认排序方式

publicstaticfinalString DEFAULT_SORT_ORDER="_id desc";

}

}

ContentProvider---ContentProvider初步相关推荐

  1. Android10.0 ContentProvider原理分析

    原文地址:https://skytoby.github.io/2019/ContentProvider%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90/ 基于Android10 ...

  2. 【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application 二 )

    文章目录 一. ActivityThread 中的 installProvider 方法 ( 创建 ContentProvider 内容提供者 ) 二. installProvider 方法的第三分支 ...

  3. Android系统(204)---ContentProvider

    Android:关于ContentProvider的知识都在这里了! 前言 ContentProvider属于 Android的四大组件之一 本文全面解析了 ContentProvider ,包括Co ...

  4. Android中ContentProvider组件详解

    一.Android四大组件 Android四大组件是Activity, Service, Content Provider,Broadcast Receiver. Activity作为程序界面,直接与 ...

  5. Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容...

    一.什么是ContentProvider? ContentProvider直译过来就是内容提供者,主要作用就是A应用提供接口给B应用调用数据,和之前介绍的sharedPreference和直接开放文件 ...

  6. ContentProvider介绍

    一.什么是ContentProvider ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作. ContentPr ...

  7. Android之ContentProvider

    文章目录 简介 ContentResolver.ContentProvider和URI Uri简介 Uri处理 自定义ContentProvider 1. 新建类继承ContentProvider 2 ...

  8. Android数据库与ContentProvider

    数据库基本概念: 数据库是"按照数据结构来组织.存储和管理数据的仓库".是一个长期存储在计算机内的.有组织的.可共享的.统一管理的大量数据的集合. 数据库的种类 最常用的数据库模型 ...

  9. Android基础——ContentProvider和contentResolver

    ContentProvider ContentProvider和contentResolver是什么? ContentResolver使用 URI是什么? URI解析 增 删 改 查 ContentP ...

  10. Carson带你学Android:关于ContentProvider的知识都在这里了!

    前言 ContentProvider属于 Android的四大组件之一 本文全面解析了 ContentProvider ,包括ContentProvider 原理.使用方法 & 实例讲解,希望 ...

最新文章

  1. php接收不到ajax请求参数,我是否需要在ajax请求和接收该请求的php之间编码/解码查询参数?...
  2. 网络抓包wireshark
  3. cgicc thttpd经常用的调试命令
  4. 【转】C++ const用法 尽可能使用const
  5. 老刘在微软Ignite China大会上聊低代码
  6. assert和if的使用
  7. matlab表白_撩妹攻略|理工男专属情人节表白礼物来啦~
  8. js-事件处理(重点)
  9. SEGGER J-Flash烧写SN号(serial number)的两种方式
  10. SourceTree这是一个无效源路径(更改git账号和密码导致无效源路径看这里)
  11. AUC(ROC曲线下方的面积大小)
  12. win 10常见蓝屏原因及解决方法
  13. 浅谈ERP数据的重要性
  14. 篮球——NBA球队队标
  15. 2013年系统架构师考试题详解
  16. 英雄联盟服务器维护时间是多久,英雄联盟更新维护到几点今天? LOL10月15日停机维护多久几点开服...
  17. 微软牵手大疆打造先进无人机技术
  18. 百度知道怎么引流减肥粉?想要打破粉丝瓶颈,必须要借助一个有力的平台
  19. python set集合的基本运算
  20. TLM通信 — UVM

热门文章

  1. win10远程桌面连接都有哪些工具
  2. 项目开发中,数据库是怎么设计的?
  3. IK分词器-自定义分词
  4. 计算机网络:CSMA/CA协议
  5. base64编码类------原始码(C#)
  6. IP RAN基站回传中的三大组网方案
  7. Hash(散列)冲突解决之线性探测再散列和二次探测再散列
  8. Cookie是什么及用法详解
  9. 如何提高项目估算精准度 关键有3方面
  10. C\C++中getchar()函数