Uri、URL、UriMatcher、ContentUris详解
1. URI:統一資源標識符
URI是統一資源標識符,是一個用于標識某一互聯網資源名稱的字符串。 該種標識允許用戶對任何(包括本地和互聯網)的資源通過特定的協議進行交互操作。URI由包括確定語法和相關協議的方案所定義。由是三個組成部分:訪問資源的命名機制、存放資源的主機名、資源自身的名稱,由路徑表示。
1.1 URI的使用方法
schema:用來說明一個ContentProvider 控制哪些數據。”content://”
authority:主機名或授權,它定義了是哪個ContentProvider 提供這些數據
path:路徑,URI 下的某一個Item。
ID:通常定義Uri 時使用”#”號占位符代替, 使用時替換成對應的數字
content://com.itheima.provider/person/#:#表示數據id(#代表任意數字)
content://com.itheima.provider/person/:來匹配任意文本。
為系統的每一個資源給其一個名字,比方說通話記錄。
1、每一個ContentProvider都擁有一個公共的URI,這個URI用于表示這個ContentProvider所提供的數據。
2、Android所提供的ContentProvider都存放在android.provider包中。 將其分為A,B,C,D 4個部分:
A:標準前綴,用來說明一個Content Provider控制這些數據,無法改變的;”content://”
B:URI 的標識,它定義了是哪個Content Provider提供這些數據。對于第三方應用程序,為了保證URI標識的唯一性,它必須是一個完整的、小寫的 類名。這個標識在 元素的 authorities屬性中說明:一般是定義該ContentProvider的包.類的名稱;”content://hx.android.text.myprovider”
C:路徑,不知道是不是路徑,通俗的講就是你要操作的數據庫中表的名字,或者你也可以自己定義,記得在使用的時候保持一致就ok了;”content://hx.android.text.myprovider/tablename”
D:如果URI中包含表示需要獲取的記錄的ID;則就返回該id對應的數據,如果沒有ID,就表示返回全部; “content://hx.android.text.myprovider/tablename/#” #表示數據id
通用資源標志符(Universal Resource Identifier, 簡稱”URI”)。
Uri代表要操作的數據,Android上可用的每種資源 - 圖像、視頻片段等都可以用Uri來表示。
URI一般由三部分組成:
- 訪問資源的命名機制。
- 存放資源的主機名。
- 資源自身的名稱,由路徑表示。
Android的Uri由以下三部分組成: “content://”、數據的路徑、標示ID(可選)舉些例子,如:
- 所有聯系人的Uri: content://contacts/people
- 某個聯系人的Uri: content://contacts/people/5
- 所有圖片Uri: content://media/external
- 某個圖片的Uri:content://media/external/images/media/4
1.2 URI常用方法
| withAppendedPath() | 追加路徑 |
| encode() | |
| fromFile() | 從一個文件新建一個uri |
| parse() | 解析uri |
| getScheme() | 獲取uri中的schema部分 |
| getLastPathSegment() |
我們很經常需要解析Uri,并從Uri中獲取數據。
Android系統提供了兩個用于操作Uri的工具類,分別為UriMatcher 和ContentUris 。
雖然這兩類不是非常重要,但是掌握它們的使用,會便于我們的開發工作。下面就一起看一下這兩個類的作用。
2. UriMatcher
UriMatcher 類主要用于匹配Uri。使用方法如下
首先第一步,初始化:
第二步注冊需要的Uri:
matcher.addURI("com.yfz.Lesson", "people", PEOPLE); matcher.addURI("com.yfz.Lesson", "person/#", PEOPLE_ID);第三部,與已經注冊的Uri進行匹配:
Uri uri = Uri.parse("content://" + "com.yfz.Lesson" + "/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; } Uri uri = Uri.parse("content://" + "com.yfz.Lesson" + "/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;}match方法匹配后會返回一個匹配碼Code,即在使用注冊方法addURI時傳入的第三個參數。上述方法會返回”vnd.android.cursor.dir/person”.
總結:
- 常量 UriMatcher.NO_MATCH 表示不匹配任何路徑的返回碼
- # 號為通配符
- * 號為任意字符
另外說一下,官方SDK說明中關于Uri的注冊是這樣寫的:
private static final UriMatcher sURIMatcher = new UriMatcher(); static { sURIMatcher.addURI("contacts", "/people", PEOPLE); sURIMatcher.addURI("contacts", "/people/#", PEOPLE_ID); sURIMatcher.addURI("contacts", "/people/#/phones", PEOPLE_PHONES); sURIMatcher.addURI("contacts", "/people/#/phones/#", PEOPLE_PHONES_ID); sURIMatcher.addURI("contacts", "/people/#/contact_methods", PEOPLE_CONTACTMETHODS); sURIMatcher.addURI("contacts", "/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID); sURIMatcher.addURI("contacts", "/deleted_people", DELETED_PEOPLE); sURIMatcher.addURI("contacts", "/phones", PHONES); sURIMatcher.addURI("contacts", "/phones/filter/*", PHONES_FILTER); sURIMatcher.addURI("contacts", "/phones/#", PHONES_ID); sURIMatcher.addURI("contacts", "/contact_methods", CONTACTMETHODS); sURIMatcher.addURI("contacts", "/contact_methods/#", CONTACTMETHODS_ID); sURIMatcher.addURI("call_log", "/calls", CALLS); sURIMatcher.addURI("call_log", "/calls/filter/*", CALLS_FILTER); sURIMatcher.addURI("call_log", "/calls/#", CALLS_ID); }這個說明估計已經是Google官方沒有更新,首先是初始化方法,沒有傳參,那么現在初始化時,實際是必須傳參的。 可以看一下Android2.2的源碼,無參數的構造方法已經是private的了。
另外就是addURI這個方法,第二個參數開始時不需要”/”, 否則是無法匹配成功的。
| addURI(String authority, String path, int code) | code:表示匹配成功以后的返回值 |
| match() | 匹配uri |
3. ContentUris
ContentUris 類用于獲取Uri路徑后面的ID部分
1、為路徑加上ID: withAppendedId(uri, id)
比如有這樣一個Uri
通過withAppendedId方法,為該Uri加上ID
Uri resultUri = ContentUris.withAppendedId(uri, 10);最后resultUri為: content://com.yfz.Lesson/people/10
2、從路徑中獲取ID: parseId(uri)
Uri uri = Uri.parse("content://com.yfz.Lesson/people/10") long personid = ContentUris.parseId(uri);最后personid 為 :10
附上實驗的代碼:
public class Lesson_14 extends Activity { private static final String AUTHORITY = "com.yfz.Lesson"; private static final int PEOPLE = 1; private static final int PEOPLE_ID = 2; //NO_MATCH表示不匹配任何路徑的返回碼 private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, "people", PEOPLE); //這里的#代表匹配任意數字,另外還可以用*來匹配任意文本 sURIMatcher.addURI(AUTHORITY, "people/#", PEOPLE_ID); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Logger.d("------ Start Activity !!! ------"); Uri uri1 = Uri.parse("content://" + AUTHORITY + "/people"); Logger.e("Uri:" + uri1); Logger.d("Match 1" + getType(uri1)); Uri uri2 = Uri.parse("content://" + AUTHORITY + "/people" + "/2"); Logger.e("Uri:" + uri2); Logger.d("Match 2" + getType(uri2)); //拼接Uri Uri cUri = ContentUris.withAppendedId(uri1, 15); Logger.e("Uri:" + cUri); //獲取ID long id = ContentUris.parseId(cUri); Logger.d("Uri ID: " + id); } private String getType(Uri uri) { int match = sURIMatcher.match(uri); switch (match) { case PEOPLE: return "vnd.android.cursor.dir/person"; case PEOPLE_ID: return "vnd.android.cursor.item/person"; default: return null; } } }ContentUris 是解析Uri 的一個工具類,可以將Uri 中的id 給解析出來
| parseId(uri) | 獲取path中的數據 |
| withAppendedId(uri, id) | 使用ContentUris工具類將id追加到uri中,返回給客戶 |
4. URL:統一資源定位符
統一資源定位符也就是說根據URL能夠定位到網絡上的某個資源,它是指向互聯網“資源”的指針。是對可以從互聯網上得到的資源的位置和訪問方法的一種簡潔的表示,是互聯網上標準資源的地址。互聯網上的每個文件都有一個唯一的URL,它包含的信息指出文件的位置以及瀏覽器應該怎么處理它。
每個URL都是URI,但不一定每個URI都是URL。這是因為URI還包括一個子類,即統一資源名稱(URN),它命名資源但不指定如何定位資源。
比如百度URL即是http://www.baidu.com
5. URI、URL 和 URN
URI 是統一資源標識符,而 URL 是統一資源定位符。因此,籠統地說,每個 URL 都是 URI,但不一定每個 URI 都是 URL。這是因為 URI 還包括一個子類,即統一資源名稱 (URN),它命名資源但不指定如何定位資源。
總結
以上是生活随笔為你收集整理的Uri、URL、UriMatcher、ContentUris详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android XML 实例化的过程
- 下一篇: 实现圆形图片