
- 英文缩写
- URI
- 应 用
- 万维网
- 外文名
- Uniform Resource Identifier
- 释 义
- 是一个用于标识某一互联网资源名称的字符串
- 中文名
- 统一资源标识符
- 性 质
- 电脑术语
-
2021-01-12 14:16:27
一、Uri简介
URI(Universal Resource Identifier)通用资源标识符
Uri和URI的区别:Uri是Android开发的,扩展了Java中的一些功能来特定的适用于Android开发,所以,在开发时,只使用Android提供的 Uri 即可。
Uri代表要操作的数据,Android里面的每种可用的资源,包括图像、视频、联系人等都可以用Uri来表示。
二、Uri组成
Uri的组成一般有三部分组成:
访问资源的命名机制、存放资源的主机名、资源自身的名称
例如解释:https://blog.csdn.net/qq_12345/article/details/7777777
例如,所有联系人的Uri:
content://contacts/people
某张图片的Uri:
content://media/external/images/media/4
以下述Uri为例
content://com.android.providers.media.documents/document/image:1598915
- uri.getScheme():content
指的是Uri协议 - uri.getAuthority():com.android.providers.media.documents
文件提供器标识 - uri.getPath():document/image:1598915
获取文件提供器之后的路径 - uri.getPathSegments():[document, image:158975]
获取文件提供器之后的路径,以File.separator切分成数组(自动解码) - uri.withAppendedPath(uri, segment):content://com.android.providers.media.documents/image:1598915/segment
在uri最后添加一个子路径
三、Uri格式
不同类别Uri的格式:
比如
第一行的图片表示,系统自带的文件管理器中的图片的Uri的格式;
第二行的图片表示,第三方集成到系统管理器中的图片的Uri的格式。序号 类别 Uri 1 图片 content://com.android.providers.media.documents/document/image%3A1598915 - 图片 content://media/external/images/media/1508729 2 视频 content://com.android.providers.media.documents/document/video%3A1594850 - 视频 content://media/external/video/media/1594849 3 音频 content://com.android.providers.media.documents/document/audio%3A920365 4 下载 content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ftest.txt 5 手机 content://com.android.externalstorage.documents/document/primary%3Atest.txt 6 文件管理器 file:///storage/emulated/0/test.txt 7 文件管理器 content://com.jinghong.fileguanlijh.FILE_PROVIDER/storage_root/Android/log.txt 8 ES文件管理器 content://com.estrongs.files/storage/emulated/0/test.txt 9 文件管理器 content://com.tencent.mtt.fileprovider/QQBrowser/test.txt 上面的%3A指的是冒号
四、Uri分类
- 系统的内容提供器
- 第三方的内容提供器
- 旧式file类型的uri
系统的内容提供器创建的文件都是来自DocumentsProvider
使用DocumentsContract.isDocumentUri(context, uri)可以判断该uri是否来自系统内容提供器。五、内容提供器(重点)
文件存储、SP存储以及数据库存储这些持久化技术所保存的数据都只能在当前应用程序中访问,虽然文件和SP存储中提供了MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE这两种操作模式,用于供给其它的应用程序访问当前应用的数据,但是这两种模式在Android 4.2中已被废弃,因为Android官方不推荐使用这种方式来实现程序跨程序数据共享的功能,而是应使用内容提供器技术。
内容提供器的用法一般有两种:
- 使用现有的内容提供器来读取和操作相应程序中的数据
- 创建自己的内容提供器给我们程序的数据提供外部访问接口
5.1 ContentResolver
对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolver类,可以通过Context中的getContentResolver()方法获取到该类的实例。ContentResolver中提供了一系列的方法用于对数据进行CRUD操作。
不同于SQLiteDatabase,ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容Uri。
内容Uri给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path。- authority用于对不同的应用程序做区分,一般为了避免冲突,都会采用程序包名的方式来进行命名。比如某个程序的包名是com.example.app,那么该程序对应的authority就可以命名为com.example.app.provider。
- path用于对同一应用程序中不同的表做区分,通常都会添加到authority的后面。比如某个程序的数据库里存在两张表:table1和table2,这时就可以将path分别命名为/table1和/table2。
- 将authority和path进行组合,内容URI就变成了 com.example.app.provider/table1 和 com.example.app.provider/table2,
在字符串的头部加上协议声明,因此内容URI最标准的格式写法即为(以第一个为例):
content://com.example.app.provider/table1
除此之外,我们还可以在这个内容Uri的后面加上一个id:
content://com.example.app.provider/table1/1
表示调用方期望访问的是com.example.app这个应用的table1表中id为1的数据。
内容Uri的格式主要就只有以上两种: 以路径结尾表示期望访问该表中所有的数据;以id结尾表示期望访问该表中拥有相应id的数据。我们可以使用通配符的方式来分别匹配这两种格式的内容Uri,规则如下:- *:表示匹配任意长度的任意字符
- #:表示匹配任意长度的数字
所以一个能够匹配任意表的内容URI可以写成:
content://com.example.app.provider/*
一个能够匹配table1表中任意一行数据的内容Uri格式可以写成:
content://com.example.app.provider/table/#
内容URI可以非常清楚地表达出我们想要访问哪个程序中哪张表里的数据。
在得到了内容URI字符串之后,我们还需要将它解析成Uri对象才可以作为参数传入,解析的方法很简单,只需调用Uri.parse()方法就可以将内容Uri字符串解析成Uri对象了:
Uri uri = Uri.parse("content://com.example.app.provider/table1");
这时我们就可以使用这个Uri对象来查询table1表中的数据了:
Cursor cursor = getContentResolver().query( uri, projection, selection, selectionArgs, sortOrder);
这些参数的意义:
query()方法参数 对应SQL部分 描述 uri from table_name 指定查询某个应用程序下的某一张表 projection select column1, column2 指定查询的列名 selection where column = value 指定where的约束条件 selectionArgs - 为where中的占位符提供具体的值 orderBy order by column1, column2 指定查询结果的排序方式 查询完成后返回的是一个Cursor对象,可以将数据从Cursor对象中逐个读取出来了。读取的思路:通过移动游标的位置来遍历Cursor的所有行,然后再取出每一行中相应列的数据(查):
if(cursor != null){ while(cursor.moveToNext()){ String column1 = cursor.getString(cursor.getColumnIndex("column1")); int column2 = cursor.getInt(cursor.getColumnIndex("column2")); } cursor.close(); }
增:
ContentValues values = new ContentValues(); values.put("column1", "test"); values.put("column2", 1); getContentResolver().insert(uri, values);
将待添加的数据组装到ContentValues中,然后调用ContentResolver的insert()方法,将Uri和ContentValues作为参数传入即可。
改:(把column1的值清空)ContentValues values = new ContentValues(); values.put("column1", ""); getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new String[]{"test", "1"});
删:(把这条数据删除掉)
getContentResolver().delete(uri, "column2 = ?", new String[]{"1"});
5.2 创建自己的内容提供器
可以通过新建一个类去继承 ContentProvider 的方式来创建一个自己的内容提供器。ContentProvider 类中有 6 个抽象方法,我们在使用子类继承它时,需要将这6个方法全部重写:
public class MyProvider extends ContentProvider{ /* * 通常会在这里完成对数据库的创建和升级等操作 * 返回true表示内容提供器初始化成功;返回false表示失败 * 只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化 */ @Override public boolean onCreate(){ return false; } /* * 从内容提供器中查询数据 * 使用uri参数来确定查询哪张表 * projection参数用于确定查询那些列 * selection和selectionArgs用于约束查询哪些行 * sortOrder用于对结果进行排序,查询的结果存放在Cursor对象中返回 */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){ return null; } /* *向内容提供器中添加一条数据 * uri来确定要添加到的表 * 待添加的数据保存在values参数中,添加完成后,返回一个用于表示这条新纪录的Uri */ @Override public Uri insert(Uri uri, ContentValues values){ return null; } /* * 更新内容提供器中已有的数据 * 使用uri来确定更新哪一张表中的数据 * 新数据保存在values参数中,selection 和 selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回 */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs){ return 0; } /* * 从内容提供器中删除数据,使用uri参数来确定删除哪一张表中的数据 * selection 和 selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回 */ @Override public int delete(Uri uri, String selection, String[] selectionArgs){ return 0; } /* * 根据传入的内容Uri来返回相应的MIME类型 */ @Override public String getType(Uri uri){ return null; } }
任何一个应用程序都可以使用ContentResolver来访问我们程序中的数据。但是如何才能保证隐私数据不会泄露出去呢? 因为所有的CRUD操作都一定要匹配到相应的内容Uri格式才能进行,而我们不可能像UriMatcher中添加隐私数据的URI,所以这部分数据根本无法被外部程序访问到,安全问题也就不存在了。(不太理解)
5.3 内容提供器的一些属性
在Manifest中注册provider时,假设我们的内容提供器命名为 DatabaseProvider,所以android:name属性指定了DatabaseProvider的类名,authority指定为com.example.databasetest.provider,其中Exported属性表示是否允许外部程序访问我们的内容提供器,Enabled属性表示是否启动这个内容提供器。
关于内容提供器的具体实例,可以参考《第一行代码》7.2.4节。
但是android:name可以指定为
<provider> android:name="android.support.v4.content.FileProvider" ··· ··· </provider>
表示:使用默认的v4的FileProvider
具体项目中遇到的一些问题
我想要访问文件管理器中某条路径下的照片,路径类似如下:
/storage/emulated/0/Android/data/com.example.test/files/toolkit/zxy.jpg
最开始的思路是通过选择文件,看一下这个路径对应的Uri是什么,然后通过调用文件选择器(调用如下),在onActivityResult中查看到的Uri是下面这样的:
通过文件选择器,选择文件,获得uri,分享的项目:
https://pan.baidu.com/s/1d6Fp7goe0td0KRFiGboF8A
i6qtIntent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); try { startActivityForResult(Intent.createChooser(intent, getString(R.string.select_file)), FILE_SELECT_CODE); overridePendingTransition(0, 0); } catch (Exception ex) { // Potentially direct the user to the Market with OnProgressChangeListener Dialog Toast.makeText(this, getString(R.string.please_install_filemanager), Toast.LENGTH_SHORT).show(); }
@Override protected void onActivityResult(int requestCode, int resultCode, final Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_SELECT_CODE && resultCode == RESULT_OK) { shareFileUrl = data.getData(); tvShareFileUri.setText(shareFileUrl.toString()); } else if (requestCode == REQUEST_SHARE_FILE_CODE){ // todo share complete. } }
content://com.coloros.filemanager.fileprovider/root/storage/emulated/0/Android/data/com.example.test/files/toolkit/zxy.jpg
所以想着能不能获取文件管理器的包名,然后自己拼接一下,得到一个Uri,但是首先第一个问题是:
我拿不到文件管理器的包名
第二个问题是:
就算拿到包名,人家不一定按照我想要拼接的规则命名auth,我同样是取不到Uri。
然后经过大神指导,可以在自己的应用中注册一个fileprovider,然后调用getUriForFile方法拿到uri(下面写的是root-path指的是共享的文件夹为Android设备的根目录)。
xml文件可以path全部,例如:<?xml version="1.0" encoding="utf-8"?> <paths> <root-path name="all" path="." /> </paths>
在需要获取Uri的地方:
FileProvider.getUriForFile(this, "com.example.test.fileprovider", new File("/storage/emulated/0/Android/data/com.example.test/files/toolkit/zxy.jpg"));
得到的Uri为:
content://com.example.test.fileprovider/all/storage/emulated/0/Android/data/com.example.test/files/toolkit/zxy.jpg
可是这是为什么呢?
倒着来分析:1、FileProvider.getUriForFile的第二个参数是在Manifest文件中注册的auth值,第三个参数为要共享的文件,这个文件一定位于我们在path文件中添加的子目录里。
2、path文件
在res/xml目录下新建的一个xml文件,用于存放应用需要共享的目录文件。添加完共享目录后,再在元素中使用元素将res/xml中的path文件与注册的FileProvider链接起来。包含的子元素可以看关于Android7.0适配中FileProvider部分的总结
- < root-path >指的是Android设备根目录下的文件
- < files-path >指的是内部存储空间应用私有目录下的files/目录,等同于 Context.getFIlesDir() 所获取的目录路径。
- path 属性用于指定当前子元素所代表的目录下需要共享的子目录的名称,注意的是,path属性值不能使用具体的独立文件名,只能是目录名。
- name 属性用于给path属性所指定的子目录名称取一个别名。后续生成 content://Uri时,会使用这个别名代替真实的目录名,这样做是为了提高安全性。
即,相当于自己的这个应用将Android根目录设为了共享目录
疑问: 这样不会造成其他应用的隐私泄露吗?
在我的应用中甚至可以分享微信下面的内容Intent intent = new Intent(Intent.ACTION_SEND); File newFile = new File("/storage/emulated/0/Android/data/com.tencent.mm/files/tbslog/IMG20210113085644.jpg"); Uri uri = FileProvider.getUriForFile(AlbumDetailsActivity.this, "com.vbooster.vbooster_privace_z_space.fileprovider", newFile); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setType("*/*"); startActivity(Intent.createChooser(intent, "分享至:"));
但是
我获取到的以 “content://” 开头的Uri无法将多张图片分享出去,但是却可以使用"file://"开头的Uri将
uri = Uri.fromFile(new File(truePath));
的方式,将多张图片分享出去,获取到的Uri为:
file:///storage/emulated/0/Android/data/com.vbooster.vbooster_privace_z_space/files/toolkit/private_album/zfenshe n_img.jpg
分享时,需要用到Uri来找到资源:
Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri); //以file开头的URI可支持多图分享 shareIntent.setType("image/*"); startActivity(Intent.createChooser(shareIntent, "分享到"));
还需要添加:
但是如果使用 “file://” 开头的Uri会报错:W/System.err: android.os.FileUriExposedException:
原因在于:从Android7.0开始,不再允许在app中把file://Uri暴露给其他app。Google认为使用file://Uri存在一定的风险。
但是如果硬要使用"file://"的话,只能在application的onCreate()里加上:
if(Build.VERSION.SDK_INT >= 18){ StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy(builder.build()); builder.detectFileUriExposure(); }
参考文章:
1、URI和URL的区别:https://www.cnblogs.com/anke-z/p/13084107.html
2、利用 Android 系统原生 API 实现分享功能:https://juejin.cn/post/6844903602851430413#heading-0
3、关于 Android 7.0 适配中 FileProvider 部分的总结:https://blog.csdn.net/growing_tree/article/details/71190741
4、《第一行代码》
5、解决异常android.os.FileUriExposedException:https://blog.csdn.net/piaomiaozaitianya/article/details/79657397更多相关内容 - uri.getScheme():content
-
uri.dart:在Dart中使用URI的实用程序
2021-05-07 11:33:09Dart中用于处理的实用程序,主要用于解析和生成URI。 UriPattern UriPattern是用于匹配和解析URI的类的接口,就像是用于String的接口一样。 它定义了方法bool matches(Uri uri)和UriMatch match(Uri uri) 。 ... -
Android中Uri和Path之间的转换的示例代码
2021-01-05 21:17:30Android中Uri和Path之间的转换 原因 调用系统拍照应用,拍照后要保存图片,那么我们需要指定一个存储图片路径的Uri。这就涉及到如何将file path转换为Uri。有时候我们还需要根据照片的路径得到照片的media Uri,那么... -
android图片文件的路径地址与Uri的相互转换方法
2021-01-20 10:41:04一个android文件的Uri地址一般如下: content://media/external/images/media/62026 这是一张图片的Uri,那么我们如何根据这个Uri获得其在文件系统中的路径呢? 其实很简单,直接上代码: public static String ... -
python-datauri:简化数据URI操作
2021-05-27 04:52:08数据URI 数据URI操作变得容易。 这不是很可靠,并且会拒绝许多有效的数据URI。 但是,它遇到了最有用的情况:模仿类型,字符集和base64标志。 安装 $ pip install python-datauri 解析中 >> > from datauri ... -
Android Uri和文件路径互相转换的实例代码
2020-08-30 00:32:39在项目中需要用到将Uri转换为绝对路径,下面小编把Android Uri和文件路径互相转换的实例代码分享到脚本之家平台,需要的的朋友参考下吧 -
uriparser:RFC 3986 URI解析和处理库-开源
2021-05-13 07:26:04请注意,我们正在迁移到GitHub:https://github.com/uriparser/uriparser uriparser是一个严格的RFC 3986兼容URI解析库,用C89编写。 uriparser是跨平台的,快速的,支持Unicode的,并根据New BSD许可获得许可。 请... -
uri:基于 RFC-3986、PSR-7 和 PSR-17 的 PHP 7.1+(包括 PHP 8)的 URI 包装器
2021-05-29 20:42:33use Sunrise \ Uri \ Uri ; use Sunrise \ Uri \ UriFactory ; // creates a new URI $ uri = new Uri ( 'http://user:pass@localhost:3000/path?query#fragment' ); // creates a new URI with a factory (is ... -
Android Intent调用 Uri的方法总结
2021-01-20 09:06:26Android Intent调用 Uri的方法总结 //调用浏览器 Uri uri = Uri.parse(); Intent it = new Intent(Intent.ACTION_VIEW,uri); startActivity(it); //显示某个坐标在地图上 Uri uri = Uri.parse(geo:38.899533,-... -
uri:URI操作库
2021-02-05 15:04:37URI Uri软件包提供了简单直观的类来管理PHP中的URI。 你将能够 解析,构建和解析URI 从不同来源(字符串,PHP环境,基本URI,URI模板等)创建URI; 处理内部化; 从URI推断属性和特征; <?php use League \ ... -
博客《Uri详解之——Uri结构与代码提取》对应源码
2015-03-27 17:19:36博客《Uri详解之——Uri结构与代码提取》对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/44679239 -
Uri详解之——Uri结构与代码提取
2021-03-09 04:33:16一、URI与Uri大家可能经常会看到在开发时,怎么有的时候是URI,有的时候是Uri,这是怎么回事?名称如此相像的两个类是有什么区别和联系?1.所属的包不同。URI位置在java.net.URI,显然是Java提供的一个类。而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即可;
[scheme:]scheme-specific-part[#fragment]
这里分为三部分:
scheme、scheme-specific-part、fragment
如果进一步划分的话是这样子的
[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
等等……
其中authority,又可以分为host:port的形式,即再次划分后是这样的:
[scheme:][//host:port][path][?query][#fragment]
所以这是划分最细的形式,其中host:port用冒号分隔,冒号前的是host,冒号后的port;
经过上面的讲解,想必大家的Uri的结构就有所了解了,下面我们就实例看看各部分的识别方式。
[scheme:]scheme-specific-part[#fragment]
[scheme:][//authority][path][?query][#fragment]
[scheme:][//host:port][path][?query][#fragment]
先列出这三种Uri形式,好让大家对比;
针对下面一个Uri字符串来匹配一下各个部分:
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字符串为例:
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为例:
String mUriStr ="http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic";
Uri mUri = Uri.parse(mUriStr);
List pathSegList = mUri.getPathSegments();
for(String pathItem:pathSegList){
Log.d("qijian","pathSegItem:"+pathItem);
}
打出来的列表为:
getQueryParameter(String key):在上面我们通过getQuery()获取整个query字段:stove=10&path=32&id=4,getQueryParameter(String key)作用就是通过传进去path中某个Key的字符串,返回他对应的值。
String mUriStr ="http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id#harvic";
mUri = Uri.parse(mUriStr);
Log.d(tag,"getQueryParameter(\"stove\"):"+mUri.getQueryParameter("stove"));
Log.d(tag,"getQueryParameter(\"id\"):"+mUri.getQueryParameter("id"));
注意注意,我稍微更改了下字符串,把query中id的值去掉了!!!!!然后看看通过getQueryParameter("id")获取它的值会得到什么!
结果如下:
可以看到,在path中,即使针对某一个KEY不对它赋值是允许的,但在利用getQueryParameter()获取该KEY对应的值时,获取到的是null;
绝对URI:以scheme组件起始的完整格式,如http://fsjohnhuang.cnblogs.com。表示以对标识出现的环境无依赖的方式引用资源。
相对URI:不以scheme组件起始的非完整格式,如fsjohnhuang.cnblogs.com。表示以对依赖标识出现的环境有依赖的方式引用资源。
不透明URI:scheme-specific-part组件不是以正斜杠(/)起始的,如mailto:fsjohnhuang@xxx.com。由于不透明URI无需进行分解操作,因此不会对scheme-specific-part组件进行有效性验证。
分层URI:scheme-specific-part组件是以正斜杠(/)起始的,如http://fsjohnhuang.com。
更多有关本扩展和标准化(Normalization)、解析化(Resolution)、相对化(Relativization)的知识参见:《Java魔法堂:URI、URL(含URL Protocol Handler)和URN》
下面源码中演示了各个提取函数的用法及结果;
如果本文有帮到你,记得关注哦
-
android:scheme 通过uri跳转到APP应用指定Activity
2016-05-11 10:29:54android:scheme 通过uri跳转到APP应用指定Activity -
Uri详解
2019-08-27 22:59:47Android开发ContentProvider,里面有用到Uri,自己对对Uri是什么,怎么来的,这些都不是很熟悉,于是在网上找资料整理出本文。 一、URI与Uri 大家可能经常会看到在开发时,怎么有的时候是URI,有的时候是Uri,这是...Android开发ContentProvider,里面有用到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)、基本形式:
[scheme:]scheme-specific-part[#fragment]
这里分为三部分:
scheme、scheme-specific-part、fragment
(2)、进一步划分:
如果进一步划分的话是这样子的<scheme:><//authority>[path][?query][#fragment]
其中有下面几个规则:
path可以有多个,每个用/连接,比如
scheme://authority/path1/path2/path3?query#fragmentquery参数可以带有对应的值,也可以不带,如果带对应的值用=表示,如:
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的形式,即再次划分后是这样的:<scheme:><//host:port>[path][?query][#fragment]
所以这是划分最细的形式,其中host:port用冒号分隔,冒号前的是host,冒号后的port;
三、示例
经过上面的讲解,想必大家的Uri的结构就有所了解了,下面我们就实例看看各部分的识别方式。
[scheme:]scheme-specific-part[#fragment]
[scheme:][//authority][path][?query][#fragment]
[scheme:][//host:port][path][?query][#fragment]
先列出这三种Uri形式,好让大家对比;
针对下面一个Uri字符串来匹配一下各个部分:
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字符串为例:
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?stove=10&path=32&id=4
- 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为例:
String mUriStr = "http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic"; Uri mUri = Uri.parse(mUriStr); List<String> pathSegList = mUri.getPathSegments(); for (String pathItem:pathSegList){ Log.d("qijian","pathSegItem:"+pathItem); }
打出来的列表为:
- getQueryParameter(String key):在上面我们通过getQuery()获取整个query字段:stove=10&path=32&id=4,getQueryParameter(String key)作用就是通过传进去path中某个Key的字符串,返回他对应的值。
String mUriStr = "http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id#harvic"; mUri = Uri.parse(mUriStr); Log.d(tag,"getQueryParameter(\"stove\"):"+mUri.getQueryParameter("stove")); Log.d(tag,"getQueryParameter(\"id\"):"+mUri.getQueryParameter("id"));
注意注意,我稍微更改了下字符串,把query中id的值去掉了!!!!!然后看看通过getQueryParameter(“id”)获取它的值会得到什么!
结果如下:
可以看到,在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:fsjohnhuang@xxx.com。由于不透明URI无需进行分解操作,因此不会对scheme-specific-part组件进行有效性验证。
分层URI:scheme-specific-part组件是以正斜杠(/)起始的,如http://fsjohnhuang.com。更多有关本扩展和标准化(Normalization)、解析化(Resolution)、相对化(Relativization)的知识参见:《Java魔法堂:URI、URL(含URL Protocol Handler)和URN》
下面源码中演示了各个提取函数的用法及结果;
源码下载地址:http://download.csdn.net/detail/harvic880925/8539679URL - Uniform Resource Locator
当您点击 HTML 页面中的某个链接时,对应的 标签指向万维网上的一个地址。
统一资源定位器(URL)用于定位万维网上的文档(或其他数据)。网址,比如 http://www.w3school.com.cn/html/index.asp,遵守以下的语法规则:
scheme://host.domain:port/path/filename 解释: scheme - 定义因特网服务的类型。最常见的类型是 http host - 定义域主机(http 的默认主机是 www) domain - 定义因特网域名,比如 w3school.com.cn :port - 定义主机上的端口号(http 的默认端口号是 80) path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。 filename - 定义文档/资源的名称
————————————————
版权声明:本文为CSDN博主「启舰」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/harvic880925/article/details/44679239 -
Android中的URI 和Uri
2018-04-21 15:11:17一、URI与Uri大家可能经常会看到在开发时,怎么有的时候是URI,有的时候是Uri,这是怎么回事?名称如此相像的两个类是有什么区别和联系?1.所属的包不同。URI位置在java.net.URI,显然是Java提供的一个类。而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)、基本形式:
- [scheme:]scheme-specific-part[#fragment]
scheme、scheme-specific-part、fragment
(2)、进一步划分:
如果进一步划分的话是这样子的
- [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的形式,即再次划分后是这样的:
- [scheme:][//host:port][path][?query][#fragment]
三、示例
经过上面的讲解,想必大家的Uri的结构就有所了解了,下面我们就实例看看各部分的识别方式。
- [scheme:]scheme-specific-part[#fragment]
- [scheme:][//authority][path][?query][#fragment]
- [scheme:][//host:port][path][?query][#fragment]
针对下面一个Uri字符串来匹配一下各个部分:
- 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字符串为例:
- 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
- List< String> getPathSegments():上面我们的getPath()是把path部分整个获取下来:/yourpath/fileName.htm,getPathSegments()的作用就是依次提取出Path的各个部分的字符串,以字符串数组的形式输出。以上面的Uri为例:
- String mUriStr = "http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic";
- Uri mUri = Uri.parse(mUriStr);
- List<String> pathSegList = mUri.getPathSegments();
- for (String pathItem:pathSegList){
- Log.d("qijian","pathSegItem:"+pathItem);
- }
- getQueryParameter(String key):在上面我们通过getQuery()获取整个query字段:stove=10&path=32&id=4,getQueryParameter(String key)作用就是通过传进去path中某个Key的字符串,返回他对应的值。
- String mUriStr = "http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id#harvic";
- mUri = Uri.parse(mUriStr);
- Log.d(tag,"getQueryParameter(\"stove\"):"+mUri.getQueryParameter("stove"));
- Log.d(tag,"getQueryParameter(\"id\"):"+mUri.getQueryParameter("id"));
结果如下:
可以看到,在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:fsjohnhuang@xxx.com。由于不透明URI无需进行分解操作,因此不会对scheme-specific-part组件进行有效性验证。
分层URI: scheme-specific-part组件是以正斜杠(/)起始的,如http://fsjohnhuang.com。 -
Android通过uri 获取文件路径
2021-02-19 13:48:01话不多说,通过uri获取文件路径遇到了很多坑,但也最终解决了,直接上代码。 import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.... -
Android中的Uri详解
2019-10-30 11:06:07一、概述 ...Uri代表要操作的数据,Android上可用的每种资源 (图像、视频片段、网页等) 都可以用Uri来表示。从概念上来讲,URI包括URL。 Uri的通用格式为:scheme:scheme-specific-part#fragm... -
Android:从内容URI获取文件URI?
2021-05-28 10:23:16如果您的内容Uri带有content://com.externalstorage...,则可以使用此方法获取Android...public static String getPath(final Context context, final Uri uri) {final boolean isKitKat = Build.VERSION.SDK_INT &g... -
URI与URL详解
2021-03-14 23:50:00URL 与 URI很多人会混淆这两个名词。URL:(Uniform/Universal Resource Locator 的缩写,统一资源定位符)。URI:(Uniform Resource Identifier 的缩写,统一资源标识符)(代表一种标准)。关系:URI 属于 URL 更高层次... -
try_files $uri $uri/ /index.html;
2022-04-01 19:38:011. 语法介绍 # 1.假设请求 127.0.0.1/home # 2.nginx配置的location location / { root /opt/dist;...$uri 指代home文件(ip地址后面的路径,假如是127.0.0.1/index/a.png,那就指代index/a.png) $ -
今天,彻底弄懂什么是URI
2019-08-27 01:40:15又到了每周二的分享时间了,今天分享一下在网络协议中,URI的相关内容,因为在外面出差,头图没法做,就用以前的老图咯~(偷懒也这么理直气壮) URL是什么我想大家都知道,毕竟我们每天都接触着,那URI是什么呢? 那... -
Android10/11 Uri与真实路径转换--全适配
2020-07-26 00:17:16* 根据Uri获取文件绝对路径,解决Android4.4以上版本Uri转换 * * @param context * @param imageUri */ public static String getFileAbsolutePath(Context context, Uri imageUri) { if (context == null ||... -
android11以上 uri转file uri转真实路径
2021-10-31 12:23:01很久以前,曾经写过针对anddroid10 uri转file的方法:android10以上 uri转file uri转真实路径_jingzz1的博客-CSDN博客_android uri转filefun uriToFile(context: Context, uri: Uri): File? = when(uri.scheme){ ... -
Uri的使用
2019-01-22 14:42:051.Uri 通用资源标志符(Universal Resource Identifier, 简称"URI")。 Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。 URI一般由三部分组成: ,URI... -
【网络】HTTP 协议中 URI 和 URL 有什么区别?
2022-01-18 22:09:47} URL类同样也提供了转换到URI的方法 public URI toURI() throws URISyntaxException { URI uri = new URI(toString()); if (authority != null && isBuiltinStreamHandler(handler)) { String s = IPAddressUtil.... -
Android 通过Uri获取真实文件路径
2021-06-19 09:15:40private fun getRealPathApi19Above(context: Context, uri: Uri): String? { var filePath = "" try { // DocumentProvider if (DocumentsContract.isDocumentUri(context, uri)) { // External. -
nginx try_files $uri $request_filename $request_uri $document_uri介绍
2022-01-29 13:50:06try_files try_files: 例子: location / { try_files $uri $uri/ /index.php } 首先尝试打开指定path的文件,如果文件不存在,则继续打开下一个文件,如果都打不开则返回500 ...$uri:这个变量指当前的请求URI