标签: Uri

Uri详解之——Uri结构与代码提取

Uri详解之——Uri结构与代码提取

前言:依然没有前言…

 

上几篇给大家讲了ContentProvider,里面有用到Uri,可能很多同学对Uri是什么,怎么来的,这些都不是很熟悉,今天就给大家具体讲讲Uri

一、URI与Uri

大家可能经常会看到在开发时,怎么有的时候是URI,有的时候是Uri,这是怎么回事?

名称如此相像的两个类是有什么区别和联系?

  • 1.所属的包不同。URI位置在java.net.URI,显然是Java提供的一个类。而Uri位置在android.net.Uri,是由Android提供的一个类。所以初步可以判断,Uri是URI的“扩展”以适应Android系统的需要。
  • 2.作用的不同。URI类代表了一个URI(这个URI不是类,而是其本来的意义:通用资源标志符——Uniform Resource Identifier)实例。Uri类是一个不可改变的URI引用,包括一个URI和一些碎片,URI跟在“#”后面。建立并且转换URI引用。而且Uri类对无效的行为不敏感,对于无效的输入没有定义相应的行为,如果没有另外制定,它将返回垃圾而不是抛出一个异常。

看不懂?没关系,知道这个就可以了:Uri是Android开发的,扩展了Java中URI的一些功能来特定的适用于Android开发,所以大家在开发时,只使用Android 提供的Uri即可;

二、Uri结构

(1)、基本形式:

  1. [scheme:]scheme-specific-part[#fragment]

这里分为三部分:
scheme、scheme-specific-part、fragment

(2)、进一步划分:

如果进一步划分的话是这样子的

  1. [scheme:][//authority][path][?query][#fragment]

其中有下面几个规则:

  • path可以有多个,每个用/连接,比如
    scheme://authority/path1/path2/path3?query#fragment
  • query参数可以带有对应的值,也可以不带,如果带对应的值用=表示,如:
    scheme://authority/path1/path2/path3?id = 1#fragment,这里有一个参数id,它的值是1
  • query参数可以有多个,每个用&连接
    scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment
    这里有三个参数:
    参数1:id,其值是:1
    参数2:name,其值是:mingming
    参数3:old,没有对它赋值,所以它的值是null
  • 在android中,除了scheme、authority是必须要有的,其它的几个path、query、fragment,它们每一个可以选择性的要或不要,但顺序不能变,比如:
    其中”path”可不要:scheme://authority?query#fragment
    其中”path”和”query”可都不要:scheme://authority#fragment
    其中”query”和”fragment”可都不要:scheme://authority/path
    “path”,”query”,”fragment”都不要:scheme://authority
    等等……

(3)、终*划分

其中authority,又可以分为host:port的形式,即再次划分后是这样的:

  1. [scheme:][//host:port][path][?query][#fragment]

所以这是划分*细的形式,其中host:port用冒号分隔,冒号前的是host,冒号后的port;

三、示例

经过上面的讲解,想必大家的Uri的结构就有所了解了,下面我们就实例看看各部分的识别方式。

  1. [scheme:]scheme-specific-part[#fragment]
  2. [scheme:][//authority][path][?query][#fragment]
  3. [scheme:][//host:port][path][?query][#fragment]

先列出这三种Uri形式,好让大家对比;
针对下面一个Uri字符串来匹配一下各个部分:

  1. http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic  
  • scheme:匹对上面的两个Uri标准形式,很容易看出在:前的部分是scheme,所以这个Uri字符串的sheme是:http
  • scheme-specific-part:很容易看出scheme-specific-part是包含在scheme和fragment之间的部分,也就是包括第二部分的[//authority][path][?query]这几个小部分,所在这个Uri字符串的scheme-specific-part是://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4 ,注意要带上//,因为除了[scheme:]和[#fragment]部分全部都是scheme-specific-part,当然包括*前面的//;
  • fragment:这个是更容易看出的,因为在*后用#分隔的部分就是fragment,所以这个Uri的fragment是:harvic
    下面就是对scheme-specific-part进行拆分了;
    在scheme-specific-part中,*前端的部分就是authority,?后面的部分是query,中间的部分就是path
  • authority:很容易看出scheme-specific-part*新端的部分是:www.java2s.com:8080
  • query:在scheme-specific-part中,?后的部分为:stove=10&path=32&id=4
  • path:在**query:**在scheme-specific-part中,除了authority和query其余都是path的部分:/yourpath/fileName.htm
    又由于authority又一步可以划分为host:port形式,其中host:port用冒号分隔,冒号前的是host,冒号后的是port,所以:
  • host:www.java2s.com
  • port:8080

四、代码提取

上面我们通过实例讲解了肉眼识别Uri更部分的方式,但在代码中又要怎样提取呢。下面就看看Uri中提取各部分的接口,依然以上面的Uri字符串为例:

  1. http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic  
  • getScheme() :获取Uri中的scheme字符串部分,在这里即,http
  • getSchemeSpecificPart():获取Uri中的scheme-specific-part:部分,这里是://www.java2s.com:8080/yourpath/fileName.htm?
  • getFragment():获取Uri中的Fragment部分,即harvic
  • getAuthority():获取Uri中Authority部分,即www.java2s.com:8080
  • getPath():获取Uri中path部分,即/yourpath/fileName.htm
  • getQuery():获取Uri中的query部分,即stove=10&path=32&id=4
  • getHost():获取Authority中的Host字符串,即www.java2s.com
  • getPost():获取Authority中的Port字符串,即8080

另外还有两个常用的:getPathSegments()、getQueryParameter(String key)

  • List< String> getPathSegments():上面我们的getPath()是把path部分整个获取下来:/yourpath/fileName.htm,getPathSegments()的作用就是依次提取出Path的各个部分的字符串,以字符串数组的形式输出。以上面的Uri为例:
  1. String mUriStr = “http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic”;  
  2. Uri mUri = Uri.parse(mUriStr);
  3. List<String> pathSegList = mUri.getPathSegments();
  4. for (String pathItem:pathSegList){  
  5.     Log.d(“qijian”,”pathSegItem:”+pathItem);  
  6. }

打出来的列表为:
%title插图%num

  • getQueryParameter(String key):在上面我们通过getQuery()获取整个query字段:stove=10&path=32&id=4,getQueryParameter(String key)作用就是通过传进去path中某个Key的字符串,返回他对应的值。
  1. String mUriStr = “http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id#harvic”;  
  2. mUri = Uri.parse(mUriStr);
  3. Log.d(tag,“getQueryParameter(\”stove\”):”+mUri.getQueryParameter(“stove”));  
  4. Log.d(tag,“getQueryParameter(\”id\”):”+mUri.getQueryParameter(“id”));  

注意注意,我稍微更改了下字符串,把query中id的值去掉了!!!!!然后看看通过getQueryParameter(“id”)获取它的值会得到什么!
结果如下:
%title插图%num

可以看到,在path中,即使针对某一个KEY不对它赋值是允许的,但在利用getQueryParameter()获取该KEY对应的值时,获取到的是null;

五、扩展

1、 *对URI和相对URI

*对URI:以scheme组件起始的完整格式,如http://fsjohnhuang.cnblogs.com。表示以对标识出现的环境无依赖的方式引用资源。
相对URI:不以scheme组件起始的非完整格式,如fsjohnhuang.cnblogs.com。表示以对依赖标识出现的环境有依赖的方式引用资源。

2、不透明URI和分层URI

不透明URI:scheme-specific-part组件不是以正斜杠(/)起始的,如mailto:[email protected]。由于不透明URI无需进行分解操作,因此不会对scheme-specific-part组件进行有效性验证。
分层URI:scheme-specific-part组件是以正斜杠(/)起始的,如http://fsjohnhuang.com。

 

吐槽:华为手机的搜索短信问题

这两天,被测试同事的华为荣耀8搞得焦头烂额,在其他手机能正常使用的Uri,在它身上却问题多多,不得不去吐槽国内定制系统…

一开始,我的搜索操作是这样的…
private void query(String keyword) {
Uri searchUri = Telephony.MmsSms.SEARCH_URI.buildUpon().appendQueryParameter(“pattern”, keyword).build();
mQueryHandler.startQuery(0, null, searchUri, null, null, null, null);
}

虽然,这只能模糊搜索信息的内容并不能根据联系人号码去查询,手中的一加、小米手机运行是没问题的,但…华为手机运行后,得到的cursor是null…

%title插图%num
好吧,既然这样,我换个Uri试试…
content://mms-sms/conversations/

先在自己手机测下,看是否可以查询成功…OK,可以,再借同事手机来跑下…结果,崩溃了,日志如下:
android.database.sqlite.SQLiteException: no such column: group_all (Sqlite code 1): , while compiling:
SELECT thread_id, address, body, date, _id FROM (
SELECT thread_id AS tid, date * 1000 AS normalized_date, NULL AS time_body, text_only, NULL AS group_id, ct_t, msg_box, v, retr_txt_cs, ct_cls, NULL AS type, st, NULL AS address, NULL AS person, tr_id, read, m_id, NULL AS body, NULL AS addr_body, m_type, network_type, locked, resp_txt, retr_st, NULL AS error_code, NULL AS group_all, NULL AS reply_path_present, sub, NULL AS risk_url_body, rr, ct_l, NULL AS status, NULL AS subject, _id, m_size, exp, sub_cs, NULL AS group_fail, sub_id, resp_st, date, date_sent, pri, NULL AS group_sent, thread_id, read_status, d_rpt, rpt_a, NULL AS is_secret, m_cls, NULL AS service_center FROM pdu WHERE ((msg_box != 3 AND (m_type = 128 OR m_type = 132 OR m_type = 130))) GROUP BY thread_id HAVING date = MAX(date) UNION SELECT thread_id AS tid, date * 1 AS normalized_date, time_body, NULL AS text_only, group_id, NULL AS ct_t, NULL AS msg_box, NULL AS v, NULL AS retr_txt_cs, NULL AS ct_cls, type, NULL AS st, address, person, NULL AS tr_id, read, NULL AS m_id, body, addr_body, NULL AS m_type, network_type, locked, NULL AS resp_txt, NULL AS retr_st, error_code, group_all, reply_path_present, NULL AS sub, risk_url_body, NULL AS rr, NULL AS ct_l, status, subject, _id, NULL AS m_size, NULL AS exp, NULL AS sub_cs, group_fail, sub_id, NULL AS resp_st, date, date_sent, NULL AS pri, group_sent, thread_id, NULL AS read_status, NULL AS d_rpt, NULL AS rpt_a, is_secret, NULL AS m_cls, service_center FROM sms_secret WHERE ((type != 3)) GROUP BY thread_id HAVING date = MAX(date)) GROUP BY tid HAVING normalized_date = MAX(normalized_date), (OS error – 2:No such file or directory)

无法找到group_all这列…就在这时,我开始强迫症了,Google了整整几小时,找到的资料少之又少,只有在GitHub的一个Issue中看到了相同问题(https://github.com/WhisperSystems/Signal-Android/issues/6198),但是并没有解决方法,好吧,好吧…

于是又试了几个Uri,但还是崩溃报Unrecognized URI!错误…
content://mms-sms/
content://mms-sms/messages/byphone

*后,实在没办法只能放弃彩信的搜索,只允许用户搜索Sms而不是Mms-Sms:
content://sms/inbox

不得不感概:兼容问题,是一个大问题啊!!!

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速