四大组件之ContentProvider-使用系统提供的ContentProvider

Posted anddlecn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四大组件之ContentProvider-使用系统提供的ContentProvider相关的知识,希望对你有一定的参考价值。

第1节 ContentProvider介绍

ContentProvider是安卓系统的四大组件之一,可以向其他组件提供数据访问的能力。它就像是一个网站,其他组件(或者其他应用)可以通过“网址”访问它,获取需要的信息。因此它可以作为不同应用之间共享数据的一种方式。

技术分享

1.1 基础功能

我们操作一个应用的数据,无外乎四种操作方式,

  • 增:添加新的数据;
  • 删:删除已有的数据;
  • 改:修改已经的数据;
  • 查:查询已有的数据;

所以一个ContentProvider要对外提供这四种最基础的功能至少一种。

1.2 操作的对象

对数据的操作范围无外乎,

  • 单条数据的操作:每一次操作增加一条数据,删除一条数据,修改一条数据,查询特定一条数据的详细内容;
  • 多条数据的操作:每一次操作增加多条数据,删除多条数据,修改多条数据,查询符合某个特征的多条数据;

例如,我们可能会向书架上“一次放一本书”-单条增,“一次取下一本书”-单条删,“一次问书架上有多少书”-多条查。

因此,仿照网站地址的设计方式,我们可以用如下的“网络地址”来表达我们希望进行的操作是针对单一一条数据还是同时多条数据:

  • xxx.xxx.xxx/items/1:针对单一一条数据,最后的数字代表特定一本书的编号(也可以使用书的名字来代替);
  • xxx.xxx.xxx/items:针对多条数据;

“网站”只要看到以上的格式就知道,要操作的是一条数据还是多条数据了。

每个ContentProvider就是一个“网站”,每个网站都有自己的“网址”。安卓系统为这个“网址”设计了如下的结构,

scheme://authority/path
  1. scheme:固定为“content”,相当于一个网址的“http”;
  2. authority:由开发者自己确定,通常把它写成这个ContentProvider的包名,例如“com.anddle.mycontentprovider”,它就相当于网址的地址“www.google.com”;
  3. path:根据查询内容的逻辑,由开发者自己决定,通常要分成多条数据和单一数据两类;

典型的例子就像这样,

多条数据
content://com.anddle.mycontentprovider/items

单一数据
content://com.anddle.mycontentprovider/items/1

这里面,
scheme:“content”
authority:“com.anddle.mycontentprovider”
path:“items”或者“items/1”

只要定义好了前面两种原则,外界(其他组件或者其他应用)就可以获取到ContentProvider中的内容了。

第2节 使用ContentProvider

安卓系统上,提供了很多系统级的ContentProvider,我们可以直接使用。例如,

  1. Media Provider:用来查询磁盘上多媒体文件;
  2. Contacts Provider:用来查询联系人信息;
  3. Calendar Provider:用来提供日历相关信息的查询;
  4. Bookmark Provider:用来提供书签信息的查询;

它们的用法大同小异,只要使用它们对应的Uri地址就可以进行增删改查的操作了。

这里我们就用Media Provider来讲解。

2.1 MediaProvider

Media Provider作为系统级别的应用程序在系统上运行,专门负责收集多媒体文件(音频、视频、文件)相关的信息。

Media Provider在开机启动后,会在后台“监听”磁盘上文件的变化,特定情况下,会自动更新多媒体文件的信息,例如磁盘上是否增加了媒体文件,是否被删除了媒体文件,有的媒体文件名称是否发生了修改等等。

所以当任何应用想获取这类文件相关的信息时,就可以向Media Provider发起查询的请求。Media Provider帮我们完成了视频文件信息的收集,因此,当我们要查询磁盘上的多媒体信息时,就不用自己去遍历磁盘上的文件进行视频文件的收集和整理了。

2.2 Media Provider查询视频文件

  1. 确定向Media Provider发出查询请求的地址-uri,我们要查询的视频文件都是存放在外部存储地址上的,就使用指向外部存储的uri;

    //uri就是:content://media/external/video/media"
    Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  2. 确定要请求的视频文件信息。我们需要查询视频的标题、创建时间,还需要播放它时使用的文件所在地址。这些信息在Media Provider中都对应着查询它们使用的字段名称;

    String[] searchKey = new String[] {
    MediaStore.Video.Media.TITLE, -->对应文件的标题
    MediaStore.Images.Media.DATA, -->对应文件的存放位置
    MediaStore.Images.Media.DATE_ADDED -->对应文件的创建时间
    };
  3. 确定查询的条件。这个条件参数的写法就和SQL数据库语言的语法一样。这里我们不打算讲SQL语法,需要各位自己去学习了;设置成空,表示查询所有数据项,

    String where = null;
  4. 设定查询结果的排序方式,使用默认的排序方式就可以了,

    String sortOrder = MediaStore.Video.Media.DEFAULT_SORT_ORDER;
  5. 获取ContentResolver对象,让它使用前面的参数向Media Provider发起查询请求;查询的结果存放在Cursor--指标当中;

    ContentResolver resolver = getContentResolver();
    Cursor cursor = resolver.query(
                    uri,
                    searchKey, 
                    where, 
                    null, 
                    sortOrder);
  6. 遍历Cursor,得到它指向的每一条查询到的信息;当Cursor指向某条数据的时候,我们就获取它携带的每个字段的值;

    while(cursor.moveToNext())
    {
        String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
        String name = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE));
        String createdTime = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
        ......  
    }
  7. Cursor使用完了之后要把它关闭掉,

    cursor.close();

整理一下前面的各个步骤,获取外部存储上的视频资源,方式如下,

Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

String[] searchKey = new String[] {
    MediaStore.Video.Media.TITLE,
    MediaStore.Images.Media.DATA,
    MediaStore.Images.Media.DATE_ADDED
};
String [] keywords = null;
String where = null;
String sortOrder = MediaStore.Video.Media.DEFAULT_SORT_ORDER;

ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(
                    uri,
                    searchKey, 
                    where, 
                    keywords, 
                    sortOrder);

if(cursor != null)
{
    while(cursor.moveToNext())
    {
        String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
        String name = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE));

        String createdTime = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));

        ......  
    }

    cursor.close();
}

最后一点千万不要忘记,因为视频文件存放在外部存储器中,所以要在应用的androidManifest.xml文件中,添加读取外部存储器的权限,

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.anddle.anddleplayer">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ......

</manifest>



以上是关于四大组件之ContentProvider-使用系统提供的ContentProvider的主要内容,如果未能解决你的问题,请参考以下文章

四大组件之ContentProvider-ContentProvider的数据存储

四大组件之ContentProvider-轻轻松松自定义ContentProvider

Android面试四大组件之内容提供者ContentProvider

Android基础到进阶四大组件之ContentProvider详解

Android 四大组件学习之ContentProvider三

Android 四大组件之ContentProvider 访问通讯录进行增删改查操作