Content Provider的架构

Authority类似web中的域名,每个content provider会通过AndroidManifest.xml向系统注册authority,如下。其中name是类名,即如何找寻这个content provider。可以省去AndroidManifest.xml中package name,不需要写完整的类名。如android:name=".BookProvider"。

<provider android:name="SomeProvider"  android:authorities="com.your-company.SomeProvider" /> 
<provider android:name="NotePadProvider" android:authorities="com.google.provider.NotePad" />

和web的URL域名类似,content provider进行数据访问的URL为content://authority/......,例如content://com.your-company.SomeProvider/。对于Android自己提供的content provider,有时会写的比较简单,例如用contacts来代替com.google.android.contacts,如content://contacts/……。

有时注册的provider会比较复杂,例如Android的联系人信息,其uri为content://com.android.contacts/contacts,其源代码信息为如下,该provider需要读写权限。

<provider android:name="ContactsProvider2" 
    android:authorities="contacts;com.android.contacts" 
    android:label="@string/provider_label" 
    android:multiprocess="false" 
    android:readPermission="android.permission.READ_CONTACTS" 
    android:writePermission="android.permission.WRITE_CONTACTS"> 
    <path-permission 
            android:pathPrefix="/search_suggest_query" 
            android:readPermission="android.permission.GLOBAL_SEARCH"/> 
    <path-permission 
            android:pathPrefix="/search_suggest_shortcut" 
            android:readPermission="android.permission.GLOBAL_SEARCH"/> 
    <path-permission 
            android:pathPattern="/contacts/.*/photo" 
            android:readPermission="android.permission.GLOBAL_SEARCH"/> 
    <grant-uri-permission android:pathPattern=".*" /> 
</provider>

Content URI的结构。Android通过Content URI来获取数据,并返回具有行列结构的游标cursor。content UI的格式为:

content://<authority-name>/<path-segment1>/<path-segment2>/etc 
例子:content://com.google.provider.NotePad/notes/23

例子的/notes表示collection,或理解为一个目录,称为path segment,而/23表示特定的item,是具体的index,content provider提供的是二维数据,这就是该row的_id值。

MIME Type。HTTP响应会带有MIME Type,最长江就是text/html,告知body的数据类型。Content Provider也一样,可以用方法获得MIME。MIME由两部分组成:type/subtype,具体可以参考rfc2046。type和subtype的定义可以在IANA中查到。下面是MIME的几个例子:

text/xml 
application/rtf 
application/vnd.ms-excel  //vnd是vendeor-specific,厂家自定义格式,如此处的微软excel格式 
application/x-tar                //x-表示自定义的私有格式

在Content Provider中可以存在多层目录,即存在item和collection,相应地分别有item的MIME tye和collection的MIME type。Android采用namespace的方式定义type和subtype。如下:

vnd.android.cursor.item/vnd.<yourcompanyname.contenttype> 是item的MIME type 
vnd.android.cursor.dir/vnd.<yourcompanyname.contenttype>是collection的MIME type

从上面的格式可以看到,type已指定,开发者只能对subtype进行设置。

定义清晰描述。我们应该为所创建的content provider提供清晰的定义或描述,可通过所使用的Uri进行constant的预定义。例如MediaStore.Images.Media.INTERNETAL_CONTENT_URI表示content://media/internal/images。同时我们也应为个列

小例子:读取联系人信息。Provider通过uri去访问,返回游标(cursor),我们将通过下面的小例子进行验证,先进行Uri的了解,然后对cursor进行二次轮询,一次采用while,一次采用for方式。正如前面的contact provider在xml的定义所示,有读写权限限制,因此在XML中应赋予相应的权限:<uses-permission android:name="android.permission.READ_CONTACTS" />

private void contentProviderTest(){ 
        /* Contact的内容很多,我们只选取部分列名字,相当于SELECT xxxx FROM ....中的xxxx。如果是自己创建创建的Content Provider,也应当采用constant的方式了明晰表示每项的内容*/ 
        String[] contactProjection = new String[]{ 
                Contacts._ID,    /* 每一行都有一个唯一的_id来表示 */ 
                Contacts.DISPLAY_NAME_PRIMARY 
        };

/* 下面是一些uri的操作,作为测试,通过provider的Uri都会提供constant的方式 */ 
        Uri peopleBaseUri = ContactsContract.Contacts.CONTENT_URI; 
        showInfo(peopleBaseUri.toString());  //showInfo( )信息显示,我将在TextView中呈现内容 
        Uri myPersonUri = Uri.withAppendedPath(peopleBaseUri, "1"); 
        showInfo(myPersonUri.toString());  
         
        /* managedQuery( )从Content Provider读取数据,返回Cursor 
         * 第1参数:Uri uri表示URI;  
         * 第2参数:String[] projection表示所需读取的信息; 
         * 第3参数:String selection数是限制条件,类似SQL中的WHERE,但去掉了“WHERE”; 
         * 第4参数:String[] selectionArgs和第3个参数配合使用,具体描述第三个参数中的“?”为何; 
         * 第5参数:String sortOrder,类似于SQL中的ORDER BY */
 
        @SuppressWarnings("deprecation") //在API Level 11,也就是Android3.0后由CursorLoader替代,为了不使Eclipse报警告,我们先在此禁止警告。看到Eclipse有个小三角的告警说明,觉得不舒服,干掉它。^_^ 
        Cursor cur = managedQuery(ContactsContract.Contacts.CONTENT_URI, 
                                contactProjection, 
                                null, 
                                null, 
                                null);  
       showInfo("query Contacts get cursor : " + cur); 
       showInfo("cursor has " + cur.getCount() + " rows."); 
        
        // 轮询方式一:  通过while 
        showInfo("read from cursor"); 
        //游标是rows的集合,首先需要使用moveToFirst(),因为query后游标是位于第一行的前面。返回false,表示为空。 
        if(!cur.moveToFirst()){ 
            showInfo("no rows. It's empty"); 
            cur.close(); 
            return; 
        } 
        
        //游标可以前后移动,去可以查看不同行的数据,还可以指定特定的行,它的移动非常灵活。游标对数据的获取是基于column number,可通过列名来获取。  
        int nameColumnIndex = cur.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY);  
        showInfo("\t Name: " + cur.getString(nameColumnIndex)); 
        while(cur.moveToNext()){  
            showInfo("\t Name: " + cur.getString(nameColumnIndex)); 
        } 
        
        //轮询方式二:通过for  
        showInfo("read from cursor again"); 
        for(cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()){ 
            String name = cur.getString(nameColumnIndex); 
            showInfo("\t Name: " + name); 
        } 
        
        cur.close(); 
    }

Where条件的用法。查找特定的数据,可以利用Uri,也可以利用manageQuery()方法的参数。例如希望查询select * from notes where _id=23,利用Uri,可以设置为

String noteUri = “content://com.google.progider.NotePad/notes/23”;

利用manageQuery( )中的selection擦数,同样可以表达为

managedQuery(uri, //为"content://com.google.provider.NotePad/notes" 
                          null,  
                          "_id=?" , 
                          new String[] {23} ,  
                          null);

增加、修改、删除数据。增删改查是数据读写的四大功能,我们将在后面的小例子中给出详细的说明。

相关链接: 我的Android开发相关文章

转自http://blog.csdn.net/flowingflying/article/details/9217431

【转】Pro Android学习笔记(六):了解Content Provider(中)的更多相关文章

  1. 【转】 Pro Android学习笔记(六九):HTTP服务(3):HTTP POST MultiPart

    目录(?)[-] 建立测试环境 开发环境导入第三方JAR HTTP Post Multipart小例子 HTTP POST不仅可以通过键值对传递参数,还可以携带更为复杂的参数,例如文件.HTTP Po ...

  2. 【转】 Pro Android学习笔记(五六):配置变化

    目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...

  3. 【转】 Pro Android学习笔记(六八):HTTP服务(2):HTTP POST

    目录(?)[-] 找一个测试网站 HTTP POST小例子 上次学习了HTTP GET请求,这次学习一下HTTP POST. 找一个测试网站 小例子好写,但要找个测试网站就有些麻烦,一下子无从入手,都 ...

  4. 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET

    目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...

  5. 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...

  6. 【转】 Pro Android学习笔记(七五):HTTP服务(9):DownloadManager

    目录(?)[-] 小例子 保存在哪里下载文件信息设置和读取 查看下载状态和取消下载 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog.csd ...

  7. 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode

    目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...

  8. 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版

    目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ...

  9. 【转】 Pro Android学习笔记(二二):用户界面和控制(10):自定义Adapter

    目录(?)[-] 设计Adapter的布局 代码部分 Activity的代码 MyAdapter的代码数据源和构造函数 MyAdapter的代码实现自定义的adapter MyAdapter的代码继续 ...

  10. 【转】 Pro Android学习笔记(十九):用户界面和控制(7):ListView

    目录(?)[-] 点击List的item触发 添加其他控件以及获取item数据 ListView控件以垂直布局方式显示子view.系统的android.app.ListActivity已经实现了一个只 ...

随机推荐

  1. 写一段代码,判断一个包括'{','[','(',')',']','}'的表达式是否合法(注意看样例的合法规则。) 给定一个表达式A,请返回一个bool值,代表它是否合法。

    这道题比较奇怪,它的匹配规则并不是我们平时想想的那种匹配规则,例如:平时的匹配规则是().{}.[]才能匹配,本题中(和} .].)都能匹配.所以做题时要好好审题.另外,本题中给的测试用例是错误的. ...

  2. 【WPF学习笔记】之如何保存画面上新建的数据到数据库中并且删除画面上的数据和数据库的数据:动画系列之(五)

    ...... 承接系列四后续: 首先,我要在用户控件2中添加“保存”,“删除”按钮. XAML代码: <UserControl x:Class="User.uc_item" ...

  3. vagrant 介绍,安装与使用

    可以帮你统一团队成员的开发环境.如果你或者你的伙伴创建了一个Vagrantfile,那么你只需要执行vagrant up就行了,所有的软件都会安装并且配置好.团队成员可以通过相同的Vagrantfil ...

  4. iOS - web自适应宽高(预设置的大小)

    //web自适应宽高 -(void)webViewDidFinishLoad:(UIWebView *)webView { NSLog(@"wessd"); [ webView s ...

  5. webpy使用mysql数据库操作(web.database)

    webpy_web.database模块 webpy框架中使用mysql管理数据库有两种方法,一种是使用python里面的MySQLdb模块: import MySQLdb 还有一种就是用webpy自 ...

  6. php加速器: xcache

    1.准备软件包 xcache-3.2.0.tar.gz 2.安装组件 $ echo 'export LC_ALL=C' >> /etc/profile $ tail -l /etc/pro ...

  7. mysql系列之5.mysql备份恢复

    备份数据: mysqldump #mysqldump -uroot -p123456 test > /test_bak.sql #egrep -v "#|\*|--|^$" ...

  8. 2017-2018-1 20179209《Linux内核原理与分析》第五周作业

    一.实验:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 环境说明 实验环境为 Ubuntu16.10 和 实验楼环境. 选择39号系统调用实验.39号系统调用为mkdir系统调用. ...

  9. 洛谷2483 k短路([SDOI2010]魔法猪学院)

    题目请戳这里 一句话题意: 给你一张n个节点,m条单向边的图,求1到n第k短的路. emmm,纪念第一个黑题(我是真的菜啊!!) 这题目还是很难的,本蒟蒻只会被洛谷卡掉的A(所以就愉快地特判了),首先 ...

  10. 特殊例子--JavaScript代码实现图片循环滚动效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...