android contentProvider

除了共享内存(SDCard)的数据外,其他包括SQLite、SharedPreferences都是仅限于被当前所创建的应用访问,而无法使它们的数据在应用程序之间交换数据,所以Android提供了ContentProvider,ContentProvider具有以下特点:

  • 应用程序间共享数据的一种方式
  • 为存储和获取数据提供统一接口
  • android为一些常见的数据提供了ContentProvider:
    • Browser:存储如浏览器的信息。
    • CallLog:存储通话记录等信息。
    • Contacts:存储联系人等信息。
    • MediaStore:存储媒体文件的信息。
    • Settings:存储设备的设置和首选项信息。
ContentProvider可以理解为一个Android应用对外开放的接口, 只要是符合它所定义的Uri格式的请求,均可以正常访问执行操作。
访问ContentProvider

ContentProvider 实例通过处理来自其他应用的请求来管理对结构化数据集的访问。所有形式的访问最终都会调用 ContentResolver,后者接着调用ContentProvider的具体方法来获取访问权限

一般使用Context.getContentResolver()方法获取ContentResolver对象。

ContentResolver 可提供insert、query、update、delete等方法.

例如,要从用户字典提供程序中获取字词及其区域设置的列表,则需调用 ContentResolver.query()。

// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   
    mProjection,                        
    mSelectionClause                  
    mSelectionArgs,                     
    mSortOrder);                        
query() 参数 SELECT 关键字/参数 备注
Uri FROM table_name Uri 映射至名为 table_name 的提供程序中的表。
projection col,col,col,... projection 是应该为检索到的每个行包含的列的数组。
selection WHERE col = value selection 会指定选择行的条件。
selectionArgs (没有完全等效项。选择参数会替换选择子句中 ? 的占位符。)
sortOrder ORDER BY col,col,... sortOrder 指定行在返回的 Cursor 中的显示顺序。
内容 URI

在Android中,Uri是一种比较常见的资源访问方式。每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。

<srandard_prefix>://<authority>/<data_path>/<id>

  • <srandard_prefix>:
    ContentProvider的标准前缀始终是content://
  • <authority>:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。一般为该ContentProvider的包.类的名称
  • <data_path>:请求的数据类型, 如数据库的表。
  • <id>:指定请求的特定数据。如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部
content://user_dictionary/words
content://com.example.app.provider/table3/1
//对应由 表table3中1标识的行的内容 URI。
content://com.example.app.provider/table3/1/name
//对应由 表table3中1标识的行的name字段内容 URI。
UriMatcher

UriMatcher会将内容 URI“模式”映射到整型值。 可以在一个 switch 语句中使用这些整型值,为匹配特定模式的一个或多个内容 URI 执行相应操作。

内容 URI 模式使用通配符匹配内容 URI:

*:匹配由任意长度的任何有效字符组成的字符串
#:匹配由任意长度的数字字符组成的字符串

假设一个具有权限 com.example.app.provider的提供程序能识别以下指向表的内容 URI:

content://com.example.app.provider/table1:一个名为 table1 的表
content://com.example.app.provider/table2/dataset1:一个名为 dataset1 的表
content://com.example.app.provider/table2/dataset2:一个名为 dataset2 的表
content://com.example.app.provider/table3:一个名为 table3 的表

可以使用以下内容 URI 模式:

content://com.example.app.provider/*
//匹配提供程序中的任何内容 URI。
content://com.example.app.provider/table2/*:
//匹配表 dataset1 和表 dataset2 的内容 URI,但不匹配 table1 或 table3 的内容 URI。
content://com.example.app.provider/table3/#
//匹配 table3 中单个行的内容 URI,
//如 content://com.example.app.provider/table3/6 对应由 6 标识的行的内容 URI。

方法 addURI() 会将权限和路径映射到一个整型值。 方法 match() 会返回 URI 的整型值。switch 语句会在查询整个表与查询单个记录之间进行选择:

public class ExampleProvider extends ContentProvider {
      ...
    // Creates a UriMatcher object.
    private static final UriMatcher sUriMatcher;

    sUriMatcher.addURI("com.example.app.provider", "table3", 1);

    sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
    ...
    // Implements ContentProvider.query()
    public Cursor query(Uri uri, String[] projection, String selection, 
                String[] selectionArgs, String sortOrder) {
        ...
        switch (sUriMatcher.match(uri)) {
            // If the incoming URI was for all of table3
            case 1:
                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                break;
            // If the incoming URI was for a single row
            case 2:
                /*
                 Because this URI was for a single row, the _ID value part is
                 present. Get the last path segment from the URI;
                 this is the _ID value.Then, append the value to the WHERE 
                 clause for the query
                 */
                selection = selection + "_ID = " uri.getLastPathSegment();
                break;

            default:
            ...
                // If the URI is not recognized, you should do some error handling here.
        }
        // call the code to actually do the query
    }
创建ContentProvider

在Android中,如果要创建自己的内容提供者的时候,需要扩展抽象类ContentProvider,并重写其中定义的各种方法。然后在AndroidManifest.xml文件中注册该ContentProvider。

创建ContentProvider的步骤:

  1. 创建一个ContentProvider的子类。
  1. 定义内容Uri
  1. 创建SQLiteOpenHelper的子类,创建一个用于存储内容的数据库。
  1. 在ContentProvider的子类中实现query()、insert()、update()、delete()、getType()、onCreate()方法。
  1. 在AndroidManifest.xml文件中注册自定义的ContentProvider。
    <provider.../>:一般只需要设置两个属性即可访问,一些额外的属性就是为了设置访问权限而存在的:
    android:name:provider的响应类。
    android:authorities:Provider的唯一标识,用于Uri匹配,一般为ContentProvider类的全名。

在实现ContentProvider的方法时需要注意一下几点:

  • 所有这些方法(onCreate() 除外)都可由多个线程同时调用,因此它们必须是线程安全方法。
  • 避免在 onCreate() 中执行长时间操作。将初始化任务推迟到实际需要时进行。
  • 尽管必须实现这些方法,但代码只需返回要求的数据类型,无需执行任何其他操作。 例如,可能想防止其他应用向某些表插入数据。 要实现此目的,可以忽略 insert() 调用并返回 0。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容