Android ContentProvider学习

Android ContentProvider学习在 Android 中 我们的应用有的时候需要对外提供数据接口 可以有如下几种方法 1 AIDL2 Broadcast3 ContentProvi nbsp nbsp nbsp nbsp 使用 AIDL 需要我们编写 AIDL 接口以及实现 而且对方也要有相应的接口描述 有点麻烦 使用 Broadcast 我们不需要任何接口描述 只要协议文档就可以了 但是这种方式不直接而且是异步的 使用 ContentPr

Android中,我们的应用有的时候需要对外提供数据接口,可以有如下几种方法:1AIDL 2Broadcast 3ContentProvider
   
 使用AIDL需要我们编写AIDL接口以及实现,而且对方也要有相应的接口描述,有点麻烦;

使用Broadcast,我们不需要任何接口描述,只要协议文档就可以了,但是这种方式不直接而且是异步的;

使用ContentProvider我们不需要接口描述,只需要知道协议,同时这种方式是同步的,使用方便。下面是ContentProvider简单介绍:

Android中的Contentprovider机制可支持在多个应用中存储和读取数据。这也是跨应用共享数据的唯一方式。在android系统中,没有一个公共的内存区域,供多个应用共享存储数据。

ContentProvider介绍:

Android有一个独特之处就是,数据库只能被它的创建者所使用,其他的应用是不能访问的,所以如果想实现不同应用之间的数据共享,就不得不用content provider了。

 Android ContentProvider数据对外的接口,只需通过使用ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保护了数据。Activity类中有一个继承自ContentWappergetContentResolver()无参数方法,该方法返回一个ContentResolver对象,通过调用其queryinsertupdatedelete方法访问数据。这几个方法的第一个参数均为URI,用来标识资源。

通常,一个应用程序可以创建自己的数据,这个数据对该应用程序来说是私有的,外界根本看不到,也不知道数据是如何存储的,是使用数据库还是使用文件,或是通过网上获得,这些一切都不重要,重要的是外界可以通过ContentProvider这一套标准及统一的接口和这个程序里的数据打交道,例 如:添加(insert)、删除(delete)、查询(query)、修改(update)
    Android
为我们提供了ContentProvider来实现数据的共享,一个程序如果想让别的程序可以操作自己的数据,就定义自己的 ContentProvider,然后在AndroidManifest.xml中注册,其他application可以通过获取ContentResolver通过Uri来操作上一程序的数据。

android自身也提供了几个现成的content providerContacts Browser,CallLog,Settings,MediaStore可在android.provider包下面找到一些android提供的Contentprovider。可以查询它们包含的数据,当然前提是已获得适当的读取权限。

 

总的来说:
1
ContentProvider为存储和读取数据提供了统一的接口
2
、使用ContentProvider,应用程序可以实现数据共享
3
android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

Uri介绍:

1、每一个ContentProvider都拥有一个公共的Uri,这个Uri用于表示这个ContentProvider提供的数据
    2
Android所提供的ContentProvider都存放在andriod.provider这个包里面

AndroidContentProvider URI有固定的形式:content://contract/people

 

标准前缀固定为content : //

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

路径people 具体的资源类型

路径的构建应根据业务而定,如下:

要操作person表中id10的记录,可以构建这样的路径:/person/10

要操作person表中id10的记录的name字段, person/10/name

要操作person表中的所有记录,可以构建这样的路径:/person

要操作xxx表中的记录,可以构建这样的路径:/xxx

当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:

要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name

如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse(“content://com.ljq.provider.personprovider/person”)

 

Android中广泛应用URI,而不是URLURL标识资源的物理位置,相当于文件的路径;而URI则是标识资源的逻辑位置,并不提供资源的具体位置。比如说电话薄中的数据,如果用URL来标识的话,可能会是一个很复杂的文件结构,而且一旦文件的存储路径改变,URL也必须得改动。但是若是URI,则可以用诸如content://contract/people这样容易记录的逻辑地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也不需要做变化,当然这都是对于用户来说,后台程序中URI到具体位置的映射还是需要程序员来改动的。

UriMatcher类使用介绍

因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcherContentUris 。掌握它们的使用,会便于我们的开发工作。
    UriMatcher
类用于匹配Uri,它的用法如下:
   
 首先第一步把你需要匹配Uri路径全部给注册上,如下:

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码

UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

//如果match()方法匹配content://com.ljq.provider.personprovider/person路径,返回匹配码为1

sMatcher.addURI(“com.ljq.provider.personprovider”, “person”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//
如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2

sMatcher.addURI(“com.ljq.provider.personprovider”, “person/#”, 2);//#号为通配符

switch (sMatcher.match(Uri.parse(“content://com.ljq.provider.personprovider/person/10”))) {

  
 case 1
    
 break;
  
 case 2
    
 break;
  
 default://不匹配

     break;
}

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.ljq.provider.personprovider/person路径,返回的匹配码为

              

ContentUris类使用介绍

ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)
用于为路径加上ID部分:

Uri uri = Uri.parse(“content://com.ljq.provider.personprovider/person”)
Uri resultUri = ContentUris.withAppendedId(uri, 10);


//生成后的Uri为:content://com.ljq.provider.personprovider/person/10

parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse(“content://com.ljq.provider.personprovider/person/10”)

long personid = ContentUris.parseId(uri);//获取的结果为:10

 

创建ContentProvider共享应用程序中的数据

实现ContentProvider的过程:(创建)

1、定义一个COTENT_URI常量
2
、定义一个类,继承ContentProvider
3
、实现query(),delete(),update(),insert(),onCreate(),getType()方法

public class PersonContentProvider extends ContentProvider{

  
 public boolean onCreate() //ContentProvider创建后就会被调用
  
 public Uri insert(Uri uri, ContentValues values)
  
 public int delete(Uri uri, String selection, String[] selectionArgs)
  
 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)// 用于供外部应用更新ContentProvider中的数据
  
 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) //用于供外部应用从ContentProvider中获取数据
  
 public String getType(Uri uri) //用于返回当前Url所代表数据的MIME类型。
}

如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,

例如:要得到所有person记录的Uricontent://com.ljq.provider.personprovider/person,那么返回的MIME类型字符串应该为:“vnd.android.cursor.dir/person”

如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,

例如:得到id10person记录,Uricontent://com.ljq.provider.personprovider/person/10,那么返回的MIME类型字符串为:“vnd.android.cursor.item/person”

 

 

4、在AndroidMainfest.xml中申明,ContentProvider采用了authorities(主机名/域名)对它进行唯一标识,你可以把ContentProvider看作是一个网站

<manifest…. >
  
 <application android:icon=”@drawable/icon” android:label=”@string/app_name”>
     
 <provider android:name=”.PersonContentProvider” 
           android:authorities
=”com.ljq.providers.personprovider”/>
  
 
application>


manifest>

 

   如果想创建自己的contentprovider,最好把自定义的URI设置为类的常量,这样简化别人的调用,并且以后如果更新URI也很容易。

 

使用已经提供ContentProvider的应用程序中的数据:

应用可以通过一个唯一的ContentResolver interface使用具体的某个content provider   

ContentResolver cr getContentResolver();  

然后就可以用ContentResolver提供的方法来使用需要的content provider了。其中contentResolver提供的方法包括query(),insert(),update()等。ContentResolver实例带的方法可实现找到指定的Contentprovider并获取到Contentprovider的数据。   

contentprovider的用户都不可能直接访问到contentprovider实例,只能通过ContentResolver在中间代理。Contentprovider返回的数据结构,是类似JDBCResultSet,在android中,Cursor对象

 

ContentProvider负责

组织应用程序的数据;

向其他应用程序提供数据;

ContentResolver则负责

获取ContentProvider提供的数据;

修改/添加/删除更新数据等;

一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProviders是以类似数据库中表的方式将数据暴露

ContentProvider应该是Android在系统启动时就创建了,否则就谈不上数据共享了。 这就要求在AndroidManifest.XML中使用元素明确定义。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220516.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午8:18
下一篇 2026年3月17日 下午8:18


相关推荐

  • AI Coding 和 AI Agent 开发这俩的关系

    AI Coding 和 AI Agent 开发这俩的关系

    2026年3月14日
    2
  • 如何使用豆包进行语音识别 豆包语音识别功能详细教程

    如何使用豆包进行语音识别 豆包语音识别功能详细教程

    2026年3月12日
    3
  • Vue的生命周期的详解

    Vue的生命周期的详解Vue 的生命周期 Vue 的生命周期是每个使用 Vue 框架的前端人员都需要掌握的知识 以此作为记录 Vue 的生命周期就是 vue 实例从创建到销毁的全过程 也就是 newVue 开始就是 vue 生命周期的开始 Vue 实例有 个完整的 命周期 也就是从开始创建 初始化数据 编译模版 挂载 Dom gt 渲染 更新 gt 渲染 卸载等 系列过程 称这是 Vue 的 命周期 钩子函数是 Vue 生命周期中每个阶段对外开放让程序员操作 Vue 的接口 Vue 有 8 个钩子函数 分别为 beforeCreate 创建前

    2026年3月26日
    2
  • django pycharm_pycharm调试django

    django pycharm_pycharm调试django前言:主要是在开发过程中一些采坑和记录,整理一下资料以防自己以后忘了,也为正在初学或者还未特别熟练使用django的同学能够避开这些,且能够系统性的学习django的使用,这里就不写目录了按照我自己的开发顺序来,大家看到专栏里面的文章顺序就是我的目录了,在本专栏里的代码争取让大家拿到就能用,做一个伸手党,网上好多代码不知道是版本原因还是其他简直是无语,不能用还一堆bug。…

    2022年8月28日
    3
  • linux连接Redis客户端

    linux连接Redis客户端linux命令下载redis-stable#官网下载,这里使用wget直接下载的[linux]$wgethttp://download.redis.io/redis-stable.tar.gz#解压[linux]$tar-xzvfredis-stable.tar.gz#进入解压目录[linux]$cdredis-stable#编译[linux]$make#拷贝入bin目录[linux]$cpsrc/redis-cli/usr/local/bin/验证redi

    2022年5月5日
    58
  • Java Integer 与 int 深刻理解

    Java Integer 与 int 深刻理解Java Integer 与 int 深刻理解

    2022年4月24日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号