URI
通用資源標志符(Universal Resource Identifier, 簡稱"URI")。
Uri代表要操作的數(shù)據(jù),Android上可用的每種資源 - 圖像、視頻片段等都可以用Uri來表示。
URI一般由三部分組成:
訪問資源的命名機制。
存放資源的主機名。
資源自身的名稱,由路徑表示。
Android的Uri由以下三部分組成: "content://"、數(shù)據(jù)的路徑、標示ID(可選)
eg:所有聯(lián)系人的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);
//與已經(jīng)注冊的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四大組件之一的內(nèi)容提供器,它主要的作用就是將程序的內(nèi)部的數(shù)據(jù)和外部進行共享,為數(shù)據(jù)提供外部訪問接口,被訪問的數(shù)據(jù)主要以數(shù)據(jù)庫的形式存在,而且還可以選擇共享哪一部分的數(shù)據(jù)。這樣一來,對于程序當中的隱私數(shù)據(jù)可以不共享,從而更加安全。contentprovider是android中一種跨程序共享數(shù)據(jù)的重要組件。
利用系統(tǒng)的ContentProvider讀取聯(lián)系人信息
Cursor cursor=cr.query(Uri.parse("content://com.android.contacts/raw_contacts"),null,null,null,null);
while(cursor.moveToNext()){
Map<String,Object> map=new HashMap<String,Object>();
int id=cursor.getInt(cursor.getColumnIndex("_id"));
String displayName=cursor.getString(cursor.getColumnIndex("display_name"));
Log.i("test",id+" "+displayName);
map.put("names",displayName);
//根據(jù)聯(lián)系人獲取聯(lián)系人數(shù)據(jù)
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
創(chuàng)建MyContentProvider繼承ContentProvider
public class MyContentProvider extends ContentProvider {
/**
* 初始化你的provider。Android系統(tǒng)在創(chuàng)建你的provider之后立即調(diào)用此方法。注意你的Provider直到一個ContentResolver對象要操作它時才會被創(chuàng)建。
*/
@Override
public boolean onCreate() {
return false;
}
/**
* 從你的provider獲取數(shù)據(jù)。使用參數(shù)來指定要查詢的表,要返回行和列,和結(jié)果的排序方式。返回一個 Cursor 對象
*/
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
/**
* 返回對應(yīng)一個content URI的MIME類型。
*/
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
/**
* 向你的provider插入一個新行。參數(shù)們指定了要選擇的表和要插入的列的值。返回一個指向新行的content URI。
*
*/
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
/**
* 從你的provider中刪除行。參數(shù)們指定了要選擇是表和要刪除的行們。返回刪除打的行的數(shù)量。
*
*/
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
/**
* 更新你的provider中已存在的行。參數(shù)中指定了要選擇的表和要更新的行以及要更新的列數(shù)據(jù)。返回更新的行的數(shù)量。
*
*/
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
在清單文件中注冊
<provider
android:name=".MyContentProvider"
android:authorities="com.study.hdq.componentdemo.MyContentProvider"
android:exported="true" />
- name:ContentProvider的全稱類名
- authorities:唯一標識了一個ContentProvider,外部應(yīng)用通過該屬性值來訪問我們的ContentProvider。因此該屬性值必須是唯一的,建議在命名時以包名為前綴
- exported:表明是否允許其他應(yīng)用調(diào)用ContentProvider,true表示支持,false表示不支持。默認值根據(jù)開發(fā)者的屬性設(shè)置而會有所不同,如果包含 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() 實現(xiàn)類似)
@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表中的所有數(shù)據(jù)
break;
case STUDENT_URI_CODE_ITEM:
// 查詢student表中的單條數(shù)據(jù)
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() 方法。它是所有的內(nèi)容提供器都必 須提供的一個方法,用于獲取 Uri 對象所對應(yīng)的 MIME 類型。一個內(nèi)容 URI 所對應(yīng)的 MIME 字符串主要由三部分組分,Android 對這三個部分做了如下格式規(guī)定。
1.必須以 vnd 開頭。
2.如果內(nèi)容 URI 以路徑結(jié)尾,則后接 android.cursor.dir/,如果內(nèi)容 URI 以 id 結(jié)尾, 則后接 android.cursor.item/。
3.最后接上 vnd.<authority>.<path>。
ContentResolver
對于每一個應(yīng)用程序來說,如果想要訪問內(nèi)容提供器中的共享數(shù)據(jù),就一定要借助ContentResolver類,可以通過Context中的getContentResolver()方法獲取到該類的實例,ContentResolver中提供了一系列的方法用于對數(shù)據(jù)進行CRUD
操作.其中insert()方法用于添加數(shù)據(jù),update()方法用于更新數(shù)據(jù),delete()方法用于刪除數(shù)據(jù),query()方法用于查詢數(shù)據(jù)
使用
Cursor cursor = getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder);
//uri from table_name 指定查詢某個應(yīng)用程序下的某一張表
//例如: 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 指定查詢結(jié)果的排序方式