内容提供器---Content Provider
2015-12-16 22:19
323 查看
Content Provider
内容提供者主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。目前,使用内容提供者是Android实现跨程序共享数据的标准方式。不同于文件存储和SharedPreferences存储中的两种全局可读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会被泄露的风险。内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中的数据,另一种是创建自己的内容提供器给我们程序提供外部访问接口。
访问其他程序中的数据
对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolve类,可以通过Context中的getContentResolver()方法获取到该类的实例。ContentResolver中提供了一系列的方法用于对数据进行增删改查操作。insert()、update()、delete()、query()等方法。
URI 内容URI给内容提供器中的数据建立了唯一标识符,主要由两部分组成,权限(authority)和路径(path)。权限是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。路径则是用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。
URL最标准的格式写法如下:
content://com.example.app.provider/table1
解析成Uri对象才可以作为参数传入,解析的方法也相当简单,代码如下:
Uri uri =Uri.parse(“content://com.example.app.provider/table1”);
增、删、改、查
查
Cursor cursor =getContentResolver().query( uri, //Uri 对象 projection, //要查询的列名 selection, //约束条件 selectionArgs, //约束条件及其值 sortOrder //指定查询结果的排序方式 );
增
ContentValues values=new ContentValues(); values.put("column1","text"); values.put("column2",1); getContentResolver().insert(uri,values);
改
ContentValues values=new ContentValues(); values.put("column1",""); getContentResolver().update(uri,values,"column1 = ? and column2 = ?",new String[]{"text",1});
删除
getContentResolver().delete(uri,"column2 = ?",new String[]{"1"});
创建自己的内容提供器
提供给外部访问接口的应用程序都是如何实现增删改查,并且保证共享数据的安全的呢?下面我们继续探究。继承ContentProvider类 public class MyProvider extends ContentProvider{ public boolean onCreate(){ return false; } public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){ return null; } public Uri insert(Uri uri,ContentValues values){ return null; } public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){ return 0; } public int delete(Uri uri,String selection,String[] selectionArgs){ return 0; } public String getType(){ return null; } } onCreate() 初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化。 query() 从内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和seletionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。 insert() 向内容提供器中添加一条数据。使用uri参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。 update() 更新内容提供器中已有的数据,返回的结果是受影响的行数将作为返回值返回。 delete() 从内容提供器中删除数据。被删除的行数将作为返回值返回。 getType() 根据传入的内容URI来返回相应的MIME类型。
匹配
使用通配符的方式来分别匹配这两种格式的内容URI,规则如下。 1、*:表示匹配任意长度的任意字符 2、#:表示匹配任意长度的数字 所以,一个能够匹配任意表的内容URI格式就可以写成: content://com.example.app.provider/* 而一个能够匹配table1表中任意一行数据的内容URI格式就可以写成: content://com.example.app.provider/table1/# 我们借助UriMatcher这个类就可以轻松地实现匹配内容URI的功能。UriMatcher中提供一个addURI()方法,这个方法接收三个参数,可以分别把权限、路径和一个自定义代码传进去。这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入,返回值是某个能够匹配这个Uri对象所对应的自定义代码,利用这个代码,我们就可以判断出调用方期望访问的是哪张表中的数据了。 public class MyProvider extends ContentProvider{ public static final int TABLE_DIR=0; public static final int TABLE_ITEM=1; public static final int TABLE2_DIR =2; public static final int TABLE2_ITEM=3; static{ uriMatcher=new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR); uriMatcher.addURI("com.example.app.provider","table1/#",TABLE_ITEM); uriMatcher.addURI("com.example.app.provider","table2",TABLE2_ITEM); uriMatcher.addURI("com.example.app.provider","table2/#",TABLE2_ITEM); } public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){ switch(uriMatcher.match(uri)){ case TABLE_DIR: //查询table1表中的所有数据 break; case TABLE_ITEM; //查询table1表中的单条数据 break; case TABLE2_DIR; //查询table2 表中的所有数据 break; case TABLE2_ITEM: //查询table2表中的单条数据 break; default: break; } } } getType()方法。它是所有的内容提供器都必须提供的一个方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要由三个部分组成,Android 对这三个部分做了如下格式规定。 1、必须以vnd开头。 2、如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。 3、最后接vnd.<authority>.<path> 如:对于content://com.example.app.provider/table1这个内容URI,它所对应的MIME类型就可以写成: vnd.android.cursor.dir/vnd.com.example.app.provider.table1
getType()逻辑:
public String getType(Uri uri){ switch(uriMatcher.match(uri)){ case TABLE_DIR: return "vnd.android.cursor.dir/vnd/com.example.app.provider/table1"; case TABLE_ITEM: return "vnd.android.cursor.item/vnd.com.example.app.provider.table1"; case TABLE2_DIR: return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2"; case TABLE2_ITEM: return "vnd.android.cursor.item/vnd.com.example.app.provider.table2"; default: break; } return null; }
注:
String bookId = uri.getPathSegments().get(1); updatedRows = db.update("Book",values,"id = ?",new String[]{bookId}); 当访问单条数据的时候,这里调用了Uri对象的getPathSegments()方法,它会将内容URI权限之后的部分以“/”符号进行分割,并把分割后的结果放入到一个字符串列表中,那这个列表的第0个位置存放的就是路径,第1个位置存放的就是id了。得到了id之后,再通过selection和selectionArgs参数进行约束,就实现了查询单条数据的功能。
内容提供器注册
全类名+权限<provider android:name="com.example.databasetest.DatabaseProvider" android:authorities="com.example.databasetest.provider"> </provider>
相关文章推荐
- Java线程间通信
- ABP理论学习之依赖注入
- ejabberd_router、ejabberd_router_multicast
- 在CDH5.5.0上安装Phoenix1.2
- 我就想知道这是为嘛。
- java.lang.RuntimeException: setAudioSource failed.
- HDU1874 畅通工程续
- 第16周项目1 验证算法(4)快速排序:
- 数据结构和算法经典100题-第22题
- python_序列构造
- 1001. 害死人不偿命的(3n+1)猜想 (15) 练习
- Secure CRT7.2安装序号
- Linux常用使用技巧
- BLIP发行历史(TinyOS中的BLIP)
- 艺术探索读书笔记(一)--Activity启动模式
- java多线程编程
- CentOS命令行模式下修改linux分辨率的方法
- github
- javascript大神修炼记(3)——条件分支
- Sublime Text3