1.Uri

通用资源标志符(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

 

 

 

 

我们很经常需要解析Uri,并从Uri中获取数据。

Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris

虽然这两类不是非常重要,但是掌握它们的使用,会便于我们的开发工作。

下面就一起看一下这两个类的作用。

 

 

2.UriMatcher

UriMatcher 类主要用于匹配Uri.

 

使用方法如下。

首先第一步,初始化:

view plain copy to clipboard print ?
  1. UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);  
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);  

第二步注册需要的Uri:

view plain copy to clipboard print ?
  1. matcher.addURI("com.yfz.Lesson""people", PEOPLE);  
  2. matcher.addURI("com.yfz.Lesson""person/#", PEOPLE_ID);  
matcher.addURI("com.yfz.Lesson", "people", PEOPLE); matcher.addURI("com.yfz.Lesson", "person/#", PEOPLE_ID);  

 

第三部,与已经注册的Uri进行匹配:

view plain copy to clipboard print ?
  1. Uri uri = Uri.parse("content://" + "com.yfz.Lesson" + "/people");  
  2. int match = matcher.match(uri);  
  3.        switch (match)  
  4.        {  
  5.            case PEOPLE:  
  6.                return "vnd.android.cursor.dir/people";  
  7.            case PEOPLE_ID:  
  8.                return "vnd.android.cursor.item/people";  
  9.            default:  
  10.                return null;  
  11.        }  
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的注册是这样写的:

view plain copy to clipboard print ?
  1. private static final UriMatcher sURIMatcher = new UriMatcher();  
  2.     static  
  3.     {  
  4.         sURIMatcher.addURI("contacts""/people", PEOPLE);  
  5.         sURIMatcher.addURI("contacts""/people/#", PEOPLE_ID);  
  6.         sURIMatcher.addURI("contacts""/people/#/phones", PEOPLE_PHONES);  
  7.         sURIMatcher.addURI("contacts""/people/#/phones/#", PEOPLE_PHONES_ID);  
  8.         sURIMatcher.addURI("contacts""/people/#/contact_methods", PEOPLE_CONTACTMETHODS);  
  9.         sURIMatcher.addURI("contacts""/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);  
  10.         sURIMatcher.addURI("contacts""/deleted_people", DELETED_PEOPLE);  
  11.         sURIMatcher.addURI("contacts""/phones", PHONES);  
  12.         sURIMatcher.addURI("contacts""/phones/filter/*", PHONES_FILTER);  
  13.         sURIMatcher.addURI("contacts""/phones/#", PHONES_ID);  
  14.         sURIMatcher.addURI("contacts""/contact_methods", CONTACTMETHODS);  
  15.         sURIMatcher.addURI("contacts""/contact_methods/#", CONTACTMETHODS_ID);  
  16.         sURIMatcher.addURI("call_log""/calls", CALLS);  
  17.         sURIMatcher.addURI("call_log""/calls/filter/*", CALLS_FILTER);  
  18.         sURIMatcher.addURI("call_log""/calls/#", CALLS_ID);  
  19.     }  
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这个方法,第二个参数开始时不需要"/", 否则是无法匹配成功的。

 

3.ContentUris

ContentUris 类用于获取Uri路径后面的ID部分

1)为路径加上ID: withAppendedId(uri, id)

比如有这样一个Uri

view plain copy to clipboard print ?
  1. Uri uri = Uri.parse("content://com.yfz.Lesson/people")  
Uri uri = Uri.parse("content://com.yfz.Lesson/people")  

通过withAppendedId方法,为该Uri加上ID

view plain copy to clipboard print ?
  1. Uri resultUri = ContentUris.withAppendedId(uri, 10);  
Uri resultUri = ContentUris.withAppendedId(uri, 10);  

最后resultUri为: content://com.yfz.Lesson/people/10

 

2)从路径中获取ID: parseId(uri)

view plain copy to clipboard print ?
  1. Uri uri = Uri.parse("content://com.yfz.Lesson/people/10")  
  2. long personid = ContentUris.parseId(uri);  
Uri uri = Uri.parse("content://com.yfz.Lesson/people/10") long personid = ContentUris.parseId(uri);  

最后personid 为 :10

 

附上实验的代码:

view plain copy to clipboard print ?
  1. package com.yfz;  
  2. import com.yfz.log.Logger;  
  3. import android.app.Activity;  
  4. import android.content.ContentUris;  
  5. import android.content.UriMatcher;  
  6. import android.net.Uri;  
  7. import android.os.Bundle;  
  8. public class Lesson_14 extends Activity {  
  9.           
  10.         private static final String AUTHORITY = "com.yfz.Lesson";  
  11.         private static final int PEOPLE = 1;  
  12.         private static final int PEOPLE_ID = 2;  
  13.           
  14.         //NO_MATCH表示不匹配任何路径的返回码   
  15.         private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
  16.         static  
  17.         {  
  18.             sURIMatcher.addURI(AUTHORITY, "people", PEOPLE);  
  19.               
  20.             //这里的#代表匹配任意数字,另外还可以用*来匹配任意文本   
  21.             sURIMatcher.addURI(AUTHORITY, "people/#", PEOPLE_ID);  
  22.         }  
  23.           
  24.         @Override  
  25.         protected void onCreate(Bundle savedInstanceState) {  
  26.             super.onCreate(savedInstanceState);  
  27.             Logger.d("------ Start Activity !!! ------");  
  28.               
  29.             Uri uri1 = Uri.parse("content://" + AUTHORITY + "/people");  
  30.             Logger.e("Uri:" + uri1);  
  31.             Logger.d("Match 1" + getType(uri1));  
  32.               
  33.             Uri uri2 = Uri.parse("content://" + AUTHORITY + "/people" + "/2");  
  34.               
  35.             Logger.e("Uri:" + uri2);  
  36.             Logger.d("Match 2" + getType(uri2));  
  37.               
  38.             //拼接Uri   
  39.             Uri cUri = ContentUris.withAppendedId(uri1, 15);  
  40.             Logger.e("Uri:" + cUri);  
  41.             //获取ID   
  42.             long id = ContentUris.parseId(cUri);  
  43.             Logger.d("Uri ID: " + id);  
  44.         }  
  45.           
  46.         private String getType(Uri uri) {  
  47.             int match = sURIMatcher.match(uri);  
  48.             switch (match)  
  49.             {  
  50.                 case PEOPLE:  
  51.                     return "vnd.android.cursor.dir/person";  
  52.                 case PEOPLE_ID:  
  53.                     return "vnd.android.cursor.item/person";  
  54.                 default:  
  55.                     return null;  
  56.             }  
  57.         }  
  58. }  
package com.yfz; import com.yfz.log.Logger; import android.app.Activity; import android.content.ContentUris; import android.content.UriMatcher; import android.net.Uri; import android.os.Bundle; 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; } } }  

 

好了,就讲这么多。

 

附:Android Uri命名格式:

ContentProvider进行数据交互时就需要用到URI。为了让客户端程序能够使用你的数据,你必须要定义一个公开的URI,它由一些固定格式的文字组成,可以分成下面几个部分:

content://

一个标准的URI前缀,它用来指示Android必须从ContentProvider中挑出一个来处理这个URI。

authority

一个唯一的标识符,标示这个URI需要查找的ContentProvider是由哪个组织开发的,一般用跟java包命名规范相似的方式来署名这个开发组织。如果是Android内置的provider,则这个authority可以省略掉,否则authority是必须的,Google建议使用用户自定义的继承ContentProvider的类的全名来作为,这个ContentProvider所要处理的URI的authority

path(路径)

ContentProvider根据这个路径信息来判断要返回什么类型的数据,所以这个后缀路径可以自由定义,但是有一些条件限制:

如果一个ContentProvider能查询返回很多种不同类型的数据,URI后缀要设置不同类型的数据所对应不同的URI后缀如内置的Contact ContentProvider就是用来处理名片夹,它可以返回很多种类型的数据:联系人、电话、联系方式等。所以对应这些不同类型的数据就有不同的URI后缀匹配:

1 content://contacts/people/1

上面是返回一个人员

1 content://contacts/people/1/phone/3

返回一个电话号码。

而且我们要为不同的数据类型设置不同的MIME类型,第一个MIME类型是:vnd.android.cursor.item/person第二个MIME类型是:vnd.android.cursor.item/phone。

同时ContentProvider不仅可以返回单条数据,也可能以目录的形式返回多条数据。以上面2个URI来说,后缀的结尾都是数字,这表示查询对应某条记录,所以返回的数据是单条的,而如果是查询目录的形式就要去掉后面的数字如:

1 2 content://contacts/people/1/phone content://contacts/people

上面就是目录形式,对应他们的MIME类型也不同,所以我们将单条的MIME类型中的item改为dir,所以MIME类型是:vnd.android.cursor.dir/phone和vnd.android.cursor.dir/person。

A: 标准前缀,表达的意思是使用ContentProvider来处理信息。

B: authority

C: 后缀1,一般用来表示请求需要获取的是哪种类型的数据(确定MIME类型的功能)。

D:定位记录。确定对应类型的数据中的哪条记录。

更多相关文章

  1. Android数据加密之Base64编码算法
  2. Android(安卓)之 ContentProvider 与 ContentResolver
  3. Android的Handler总结
  4. 在Ubuntu中和Android中添加开机自启动的守护进程
  5. android 基础知识
  6. Android(安卓)文件路径详解
  7. 从头学Android之Android的数据存储--File
  8. mybatisplus的坑 insert标签insert into select无参数问题的解决
  9. Pycharm安装PyQt5的详细教程

随机推荐

  1. Android 学习笔记3(Activity之间参数传递)
  2. PermissionsDispatcher库的使用(简单处理A
  3. Uiautomator Api浅析
  4. Android SQLite Database Tutorial
  5. Android 高仿74款APP
  6. android 结合Junit进行测试.
  7. android发送彩信的两种方法
  8. android SD卡热插拔监听
  9. Android: To Use AsyncQueryHandler
  10. android实现文件读写功能