ContentProvider

以下内容整理自互联网,仅用于个人学习


1. ContentProvider介绍

ContentProvider(内容提供者)是Android的四大组件之一,管理android以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用。

2. URI

URI(统一资源标识符)代表要操作的数据,可以用来标识每个ContentProvider,这样你就可以通过指定的URI找到想要的ContentProvider,从中获取或修改数据。

Android中URI的格式:
content://com.example.app.provider/table/1

  • content://: schema,已经由Android所规定为:content://
  • com.example.app.provider:权限(Authority),是URI的授权部分,是唯一标识符,用来定位ContentProvider。
  • table:指向一个对象集合,一般用表的名字,如果没有指定后面“1”部分,则返回全部记录。
  • 1:指向特定的记录。

通配符:

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

content://com.example.app.provider/* 匹配provider的任何内容uri
content://com.example.app.provider/table1/# 匹配table3的所有行

MIME

MIME是指定某个扩展名的文件用一种应用程序来打开,就像你用浏览器查看PDF格式的文件,浏览器会选择合适的应用来打开一样。Android中的工作方式跟HTTP类似,ContentProvider会根据URI来返回MIME类型,ContentProvider会返回一个包含两部分的字符串。

  • text/html
  • text/css
  • text/xml
  • application/pdf

一个内容URI所对应的MIME字符串主要由三个部分组成,Android对这三个部分做了格式规范:

  1. 必须以vnd开头
  1. 如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则接android.cursor.item/
  2. 最后接上vnd.<authority>.<path>

每个内容类型的Android MIME类型有两种形式:多条记录(集合)和单条记录。

//集合记录 
vnd.android.cursor.dir/自定义 
 
//单条记录  
vnd.android.cursor.item/自定义

vnd表示这些类型和子类型具有非标准的、供应商特定的形式。Android中类型已经固定好了,不能更改,只能区别是集合还是单条具体记录,子类型可以按照格式自己填写。

Android系统提供了两个用于操作Uri的工具类:ContentUris和UriMatcher。

ContentUris

ContetnUris包含一个便利的函数withAppendedId()来向URI追加一个id。

Uri uri = Uri.parse("content://cn.scu.myprovider/user") 
Uri resultUri = ContentUris.withAppendedId(uri, 7);  
//生成后的Uri为:content://cn.scu.myprovider/user/7

同时提供parseId(uri)方法用于从URI中获取ID

Uri uri = Uri.parse("content://cn.scu.myprovider/user/7") 
long personid = ContentUris.parseId(uri); 
//获取的结果为:7

UriMatcher

UriMatcher本质上是一个文本过滤器,用在contentProvider中帮助我们过滤,分辨出查询者想要查询哪个数据表。

使用UriMatcher主要步骤:

  1. 初始化
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
  1. 注册Uri
//USER 和 USER_ID是两个int型数据 
matcher.addURI("cn.scu.myprovider", "user", USER); 
matcher.addURI("cn.scu.myprovider", "user/#",USER_ID); 
//如果match()方法匹配content://cn.scu.myprovider/user路径,返回匹配码为USER
  1. 匹配已经注册的Uri
/*  
 * 如果操作集合,则必须以vnd.android.cursor.dir开头  
 * 如果操作非集合,则必须以vnd.android.cursor.item开头  
 * */   
@Override   
public String getType(Uri uri) {   
Uri uri = Uri.parse("content://" + "cn.scu.myprovider" + "/user");   
    switch(matcher.match(uri)){   
    case USER:   
        return "vnd.android.cursor.dir/user";   
    case USER_ID:   
        return "vnd.android.cursor.item/user";   
    }   
}

3. ContentProvider的主要方法

//ContentProvider创建后或打开系统后其它应用第一次访问该ContentProvider时调用。 
public boolean onCreate() 
 
//外部应用向ContentProvider中添加数据。 
public Uri insert(Uri uri, ContentValues values) 
   
//外部应用从ContentProvider删除数据。 
public int delete(Uri uri, String selection, String[] selectionArgs) 
 
//外部应用更新ContentProvider中的数据。 
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)  
   
//该方法用于返回当前Url所代表数据的MIME类型。 
public String getType(Uri uri)

4. ContentResolver

ContentResolver通过URI来查询ContentProvider中提供的数据。除了URI以 外,还必须知道需要获取的数据段的名称,以及此数据段的数据类型。如果你需要获取一个特定的记录,你就必须知道当前记录的ID。

//添加 
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)  
//获取 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

示例代码

ContentResolver resolver =  getContentResolver(); 
Uri uri = Uri.parse("content://cn.scu.myprovider/user"); 
 
//添加一条记录 
ContentValues values = new ContentValues(); 
values.put("name", "fanrunqi"); 
values.put("age", 24); 
resolver.insert(uri, values);   
 
//获取user表中所有记录 
Cursor cursor = resolver.query(uri, null, null, null, "userid desc"); 
while(cursor.moveToNext()){ 
   //操作 
} 
 
//把id为1的记录的name字段值更改新为finch 
ContentValues updateValues = new ContentValues(); 
updateValues.put("name", "finch"); 
Uri updateIdUri = ContentUris.withAppendedId(uri, 1); 
resolver.update(updateIdUri, updateValues, null, null); 
 
//删除id为2的记录 
Uri deleteIdUri = ContentUris.withAppendedId(uri, 2); 
resolver.delete(deleteIdUri, null, null);

5. ContentObserver

ContentObserver(内容观察者),目的是观察特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。

下面给出一个监听短信的例子

public class MainActivity extends Activity { 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
 
//注册观察者Observser     
this.getContentResolver().registerContentObserver(Uri.parse("content://sms"),true,new SMSObserver(new Handler())); 
 
    } 
 
    private final class SMSObserver extends ContentObserver { 
 
        public SMSObserver(Handler handler) { 
            super(handler); 
 
        } 
 
 
        @Override 
        public void onChange(boolean selfChange) { 
 
 Cursor cursor = MainActivity.this.getContentResolver().query( 
Uri.parse("content://sms/inbox"), null, null, null, null); 
 
            while (cursor.moveToNext()) { 
                StringBuilder sb = new StringBuilder(); 
 
                sb.append("address=").append( 
                        cursor.getString(cursor.getColumnIndex("address"))); 
 
                sb.append(";subject=").append( 
                        cursor.getString(cursor.getColumnIndex("subject"))); 
 
                sb.append(";body=").append( 
                        cursor.getString(cursor.getColumnIndex("body"))); 
 
                sb.append(";time=").append( 
                        cursor.getLong(cursor.getColumnIndex("date"))); 
 
                System.out.println("--------has Receivered SMS::" + sb.toString()); 
  
            } 
        }  
    } 
}

同时可以在ContentProvider发生数据变化时调用 getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者。

public class UserContentProvider extends ContentProvider { 
   public Uri insert(Uri uri, ContentValues values) { 
      db.insert("user", "userid", values); 
      getContext().getContentResolver().notifyChange(uri, null); 
   } 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 参考Content Providers 对于ContentProvider, 可以把它看做为一个数据库, 数据库中...
    AssIstne阅读 1,991评论 1 3
  • 一、使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作...
    IT枫阅读 3,940评论 0 7
  • 内容提供器 思维导图 最近在练习使用思维导图,献一下丑。。。 什么是内容提供器 内容提供器主要用于在不同应用程序间...
    HeilHelloWorld阅读 783评论 2 4
  • 《七月上》小花版,点这里点这里 初听时,很喜欢这个旋律,简单平缓,自己也唱过,然后就死在列表里。抽中后,有必要再细...
    邢姑娘阅读 233评论 0 2
  • 在初中的时候 那个时候是初三面临着中考的来临, 有一个男生从外地转学回来, 称他为A吧。 A人长得还行, 身高18...
    CHENDH阅读 244评论 0 0