赞
踩
内容提供者,一般是用于跨程序之间数据的共享。一种是利用现有的内容提供者,来读取和操作相应程序的数据。另一种是创建自己的内容提供者为其他程序使用。
想要访问内容提供者中所共享的数据,就必须要使用到ContentResolver这个类。可以通过Context中的getContentResolver()方法,获取到该类的实例,然后在这个实例的基础上进行插入,删除,更新,查询操作。
Cursor curosr = null;
curosr = getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
查询操作,在这里,通过getContentResolver来获得一个ContentResolver实例,然后利用这个实例,调用query方法进行查询。query方法接收五个参数,第一个是uri,第二个是查询的列明,是字符串数组类型,第三个是查询的where子句,第四个是where子句中占位符的匹配值,第五个是排序顺序。 该方法返回一个Cursor对象。利用这个cursor,通过cursor.getString……等,cursor.getColumnIndex等获取数据。
ContentValues contentValues = new ContentValues();
contentValues.put("title",edt_title.getText().toString());
contentValues.put("content",edt_content.getText().toString());
getContentResolver().insert(uri,contentValues);
public Uri insert(@NonNull Uri uri, ContentValues contentValues)
插入操作,就像对数据库的插入一样,把数据放在ContentValues里面,然后调用insert方法。Insert方法接收两个参数,第一个是一个uri,第二个是插入的内容ContentValues。Insert方法,返回的是一个uri。
public int update(@NonNull Uri uri, ContentValues contentValues, String selection, String[] selectionArgs)
更新操作,接收四个参数,第一个参数是一个uri,第二个参数是更新的内容,第三个参数是where子句,第四个参数是where子句占位符的匹配值。该方法返回更新的行数。
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs)
删除操作,接收三个参数,第一个是uri,第二个是where子句,第三个是where子句占位符的匹配值。该方法返回被删除的行数。
可以看到,不管是增删改查里面的哪一个方法,都有一个参数是uri。这个uri就像一个门牌号一样,可以识别出是针对哪一个程序的哪一个表哪一个记录。
public static final String AUTHORITY = "com.example.asus.beiwanglu.provider";
Uri uri = Uri.parse("content://"+AUTHORITY+"/BEIWANGLU/"+ID);
URI内存字符串:由两部分组成,一个是authority部分,一个是path部分
authority为程序的 包名.provider
path是用于对一个应用程序内不同的表进行区分。比如有表table1 那么完整的URI 应该是下面
content:// com.example.asus.beiwanglu.provider /table1
如果还需要精确到哪一行记录,则可以在表/table1的后面加上/2 这个2就代表是表table1的第二条记录,如下
content:// com.example.asus.beiwanglu.provider /table1/2
得到内容URI字符串以后,需要把它解析成Uri对象,才可以使用,利用Uri.parse(“URI内容字符串”);这样就可以上面的增删改查中使用了。
在真正使用其他程序的内容提供者的时候,需要去了解其有哪些可以匹配的uri,它提供了哪些数据进行操作等具体的信息。
前面只是获取其他程序的URI,然后通过内容提供者来访问其他程序的数据。那么那些可供外部访问的应用程序,又是如何提供这些外部访问接口的呢?现在通过自定义自己的内容提供者,来进一步的学习。
(1)创建内容提供者:
右击你的包名—new—Other—ContentProvider(当然也可以新建一个类,继承与ContentProvider,但是别忘记在配置文件中注册)
Authority指定为包名.provider。每个内容提供者都有一个authority,是唯一的,如果有多个自定义内容提供者类,需要不同用以区分。
Exported 是否允许外部程序访问该内容提供者,可以在配置文件中进行更改,true/false
Enabled 是否使能这个内容提供者,即要不要启用它
(2)在配置文件中注册内容提供者(如果你用的是新建一个类,继承于ContentProvider的方法的话)
<provider
android:authorities="com.example.asus.beiwanglu.provider"
android:name=".BEIWANGLUProvider"
android:enabled="true"
android:exported="true">
</provider>
上面的四行和(1)中的是一样的。
(3)重写内容提供者的6个方法:
自定义内容提供者,继承于ContentProvider,需要重写6个基本方法,onCreate(),insert(),update(),delete(),query(),getType()。
其中四个数据的操作方法,在上面大致介绍过。这里直接放上一段代码片段。是一个备忘录程序的自定义内容提供者
public class BEIWANGLUProvider extends ContentProvider{ public static final int BEIWANGLU_DIR = 0; //数据库中备忘录表 public static final int BEIWANGLU_ITEM = 1; //数据库中备忘录表中的某一行 public static final String AUTHORITY = "com.example.asus.beiwanglu.provider"; //URI的authority部分 private static UriMatcher uriMatcher; private BeiWangLuDatabaseHelper dbHelper; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //addURI接收三个参数为Uri对象的authority部分,path部分,以及一个自定义的int 值,起到标识作用 uriMatcher.addURI(AUTHORITY,"BEIWANGLU",BEIWANGLU_DIR); //数据库中备忘录表的Uri uriMatcher.addURI(AUTHORITY,"BEIWANGLU/#",BEIWANGLU_ITEM); //数据库中备忘录表某一行的Uri } @Override public boolean onCreate() { dbHelper = new BeiWangLuDatabaseHelper(getContext(),"BeiWangLuContent.db",null,2); return true; } @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = null; switch (uriMatcher.match(uri)){ case BEIWANGLU_DIR: cursor = db.query("BEIWANGLU",projection,selection,selectionArgs,null,null,sortOrder); break; case BEIWANGLU_ITEM: String BEIWANGLU_ID = uri.getPathSegments().get(1); cursor = db.query("BEIWANGLU",projection,"id = ?",new String[]{BEIWANGLU_ID},null,null,sortOrder); break; default: } return cursor; } @Override public String getType(@NonNull Uri uri) { switch (uriMatcher.match(uri)){ case BEIWANGLU_DIR: return "vnd.android.cursor.dir/vnd.com.example.asus.beiwanglu.provider.BEIWANGLU"; case BEIWANGLU_ITEM: return "vnd.android.cursor.item/vnd.com.example.asus.beiwanglu.provider.BEIWANGLU"; default: } return null; } @Override public Uri insert(@NonNull Uri uri, ContentValues contentValues) { SQLiteDatabase db = dbHelper.getWritableDatabase(); Uri uriReturn = null; switch (uriMatcher.match(uri)){ case BEIWANGLU_DIR: case BEIWANGLU_ITEM: long newBEIWANGLU_ID = db.insert("BEIWANGLU",null,contentValues); uriReturn = Uri.parse("content://"+AUTHORITY+"/BEIWANGLU/"+newBEIWANGLU_ID); break; } return uriReturn; } @Override public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int deleteRow = 0; switch (uriMatcher.match(uri)){ case BEIWANGLU_DIR: case BEIWANGLU_ITEM: break; } return deleteRow; } @Override public int update(@NonNull Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int updateRow = 0; switch (uriMatcher.match(uri)){ case BEIWANGLU_DIR: updateRow = db.delete("BEIWANGLU",selection,selectionArgs); break; case BEIWANGLU_ITEM: String update_ID = uri.getPathSegments().get(1); updateRow = db.update("BEIWANGLU",contentValues,"id = ?",new String[]{update_ID}); break; } return updateRow; } }
分析:
public static final int BEIWANGLU_DIR = 0; //数据库中备忘录表
public static final int BEIWANGLU_ITEM = 1; //数据库中备忘录表中的某一行
public static final String AUTHORITY = "com.example.asus.beiwanglu.provider"; //URI的authority部分
private static UriMatcher uriMatcher;
private BeiWangLuDatabaseHelper dbHelper;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//addURI接收三个参数为Uri对象的authority部分,path部分,以及一个自定义的int 值,起到标识作用
uriMatcher.addURI(AUTHORITY,"BEIWANGLU",BEIWANGLU_DIR); //数据库中备忘录表的Uri
uriMatcher.addURI(AUTHORITY,"BEIWANGLU/#",BEIWANGLU_ITEM); //数据库中备忘录表某一行的Uri
}
这一段代码,是为了匹配uri而使用的。外部程序访问该程序的时候,需要对其所传入的uri进行解析,分析出调用方是想要访问哪一张表的数据。
内容URI字符串,主要就两种格式,一个是以路径结尾,一个是以id结尾,代表想要访问表中的哪一条记录。因此,我们可以借助UriMatcher这个类,把URI的匹配格式加进去,到时候只要通过match方法,传入uri就可以知道外部程序具体想要访问的是哪一张表哪一条记录了
创建一个UriMatch对象,并且默认是无匹配的。然后调用addURI方法,第一个参数是authority,第二个参数是表名或者表的某一条记录,第三个参数是int类型,用于标识
比如上面的代码,第一行是把URI为 AUTHORITY+”BEIWANGLU”加进去,代表的是想要访问备忘录表这个表,如果外部程序使用uri为
content://+AUTHORITY+”/BEIWANGLU” 访问的时候。这时候调用uriMatcher.match(uri)。就可以得到BEIWANGLU_DIR这个标签。这样就可以判断出是想要访问备忘录表了。
如果外部程序使用的uri为content://+AUTHORITY+”/BEIWANGLU/2” 就可以知道外部程序是想要访问备忘录表的第二条数据记录
@Override
public String getType(@NonNull Uri uri) {
switch (uriMatcher.match(uri)){
case BEIWANGLU_DIR:
return "vnd.android.cursor.dir/vnd.com.example.asus.beiwanglu.provider.BEIWANGLU";
case BEIWANGLU_ITEM:
return "vnd.android.cursor.item/vnd.com.example.asus.beiwanglu.provider.BEIWANGLU";
default:
}
return null;
}
这是另一个十分重要的方法,根据传入的内容URI来返回相应的MIME类型。一个内容URI字符串所对应的MIME类型,一般由两个部分组成
第一部分:如果URI以路径结尾,则为vnd.android.cursor.dir/ 如果是以id结尾,那么就是vnd.android.cursor.item/
第二部分:vnd..
其他几个方法,相信在看了我上面的代码之后你一定对自定义内容提供者有了更多的了解。
最后,文中如有不对之处,欢迎指出。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。