URI
通用资源标志符(Universal Resource Identifier, 简称"URI")。
Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。
URI一般由三部分组成:
访问资源的命名机制。
存放资源的主机名。
资源自身的名称,由路径表示。
Android的Uri由以下三部分组成: "content://"、数据的路径、标示ID(可选)
eg:所有联系人的Uri: content://contacts/people
UriMatcher
UriMatcher 类主要用于匹配Uri.
使用方法
//初始化
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//注册需要的Uri:
matcher.addURI("com.study.hdq.componentdemo", "people", PEOPLE);
matcher.addURI("com.study.hdq.componentdemo", "person/#", PEOPLE_ID);
//与已经注册的Uri进行匹配
Uri uri = Uri.parse("content://" + "com.study.hdq.componentdemo" + "/people");
int match = matcher.match(uri);
switch (match)
{
case PEOPLE:
return "vnd.android.cursor.dir/people";
case PEOPLE_ID:
return "vnd.android.cursor.item/people";
default:
return null;
}
--常量 UriMatcher.NO_MATCH
表示不匹配任何路径的返回码
--# 号为通配符
--* 号为任意字符
ContentProvider
ContentProvider是android四大组件之一的内容提供器,它主要的作用就是将程序的内部的数据和外部进行共享,为数据提供外部访问接口,被访问的数据主要以数据库的形式存在,而且还可以选择共享哪一部分的数据。这样一来,对于程序当中的隐私数据可以不共享,从而更加安全。contentprovider是android中一种跨程序共享数据的重要组件。
利用系统的ContentProvider读取联系人信息
Cursor cursor=cr.query(Uri.parse("content://com.android.contacts/raw_contacts"),null,null,null,null);
while(cursor.moveToNext()){
Map map=new HashMap();
int id=cursor.getInt(cursor.getColumnIndex("_id"));
String displayName=cursor.getString(cursor.getColumnIndex("display_name"));
Log.i("test",id+" "+displayName);
map.put("names",displayName);
//根据联系人获取联系人数据
Cursor cursor2=cr.query(Uri.parse("content://com.android.contacts/raw_contacts/"+id+"/data"),null,null,null,null);
while(cursor2.moveToNext()){
// int type=cursor2.getInt(cursor2.getColumnIndex("mimetype_id"));
String type=cursor2.getString(cursor2.getColumnIndex("mimetype"));
String data1=null;
if ("vnd.android.cursor.item/phone_v2".equals(type)){
data1 = cursor2.getString(cursor2.getColumnIndex("data1"));
Log.i("test"," "+type+" "+data1);
map.put("phones",data1);
}
}
data.add(map);
}
Log.e(TAG,"names:"+data.get(0).get("names").toString()+" phones:"+data.get(0).get("phones").toString());
输出
com.study.hdq.componentdemo E/MainActivity: names:华为客服 phones:4008308300
自定义ContentProvider
创建MyContentProvider继承ContentProvider
public class MyContentProvider extends ContentProvider {
/**
* 初始化你的provider。Android系统在创建你的provider之后立即调用此方法。注意你的Provider直到一个ContentResolver对象要操作它时才会被创建。
*/
@Override
public boolean onCreate() {
return false;
}
/**
* 从你的provider获取数据。使用参数来指定要查询的表,要返回行和列,和结果的排序方式。返回一个 Cursor 对象
*/
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
/**
* 返回对应一个content URI的MIME类型。
*/
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
/**
* 向你的provider插入一个新行。参数们指定了要选择的表和要插入的列的值。返回一个指向新行的content URI。
*
*/
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
/**
* 从你的provider中删除行。参数们指定了要选择是表和要删除的行们。返回删除打的行的数量。
*
*/
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
/**
* 更新你的provider中已存在的行。参数中指定了要选择的表和要更新的行以及要更新的列数据。返回更新的行的数量。
*
*/
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
在清单文件中注册
- name:ContentProvider的全称类名
- authorities:唯一标识了一个ContentProvider,外部应用通过该属性值来访问我们的ContentProvider。因此该属性值必须是唯一的,建议在命名时以包名为前缀
- exported:表明是否允许其他应用调用ContentProvider,true表示支持,false表示不支持。默认值根据开发者的属性设置而会有所不同,如果包含 Intent-Filter 则默认值为true,否则为false
使用 UriMatcher
public static final String AUTHORITY = "om.study.hdq.componentdemo.MyContentProvider";
public static final int STUDENT_URI_CODE = 0;
public static final int STUDENT_URI_CODE_ITEM = 1;
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
uriMatcher.addURI(AUTHORITY, "student", STUDENT_URI_CODE);
uriMatcher.addURI(AUTHORITY, "student/#", STUDENT_URI_CODE_ITEM);
}
以 query( ) 方法为例示范(insert()、update()、delete() 实现类似)
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
switch (uriMatcher.match(uri)) {
case STUDENT_URI_CODE:
// 查询student表中的所有数据
break;
case STUDENT_URI_CODE_ITEM:
// 查询student表中的单条数据
break;
default:
break;
}
return null;
}
getType()
@Nullable
@Override
public String getType(@NonNull Uri uri) {
switch (uriMatcher.match(uri)) {
case STUDENT_URI_CODE:
return "vnd.android.cursor.dir/vnd."+AUTHORITY+".student";
case STUDENT_URI_CODE_ITEM:
return "vnd.android.cursor.item/vnd."+AUTHORITY+".student";
default:
break;
}
return null;
}
除此之外,还有一个方法你会比较陌生,即 getType() 方法。它是所有的内容提供器都必 须提供的一个方法,用于获取 Uri 对象所对应的 MIME 类型。一个内容 URI 所对应的 MIME 字符串主要由三部分组分,Android 对这三个部分做了如下格式规定。
1.必须以 vnd 开头。
2.如果内容 URI 以路径结尾,则后接 android.cursor.dir/,如果内容 URI 以 id 结尾, 则后接 android.cursor.item/。
3.最后接上 vnd.. 。
ContentResolver
对于每一个应用程序来说,如果想要访问内容提供器中的共享数据,就一定要借助ContentResolver类,可以通过Context中的getContentResolver()方法获取到该类的实例,ContentResolver中提供了一系列的方法用于对数据进行CRUD
操作.其中insert()方法用于添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数据
使用
Cursor cursor = getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder);
//uri from table_name 指定查询某个应用程序下的某一张表
//例如: Uri uri = Uri.parse("content://om.study.hdq.componentdemo.MyContentProvider/student");
//projection select column1,column2 指定查询的列名
//selection where column = value 指定where的约束条件
//selectionArgs - 为where中的占位符提供具体的值
//orderBy order by column1,column2 指定查询结果的排序方式