Android系统的问题分析笔记(9) - Android 中的 Uri 如何使用呢 ?

news2024/11/24 1:04:28

问题

Android 中常用的 uri 如何使用呢 ?(此篇分析基础为Android 7.1.1系统源码),参看Android官方说明:https://developer.android.com/reference/android/net/Uri,代码可在此查看:https://github.com/LineageOS/android_frameworks_base/blob/lineage-20.0/core/java/android/net/Uri.java

1 概述

  通用资源标志符 URI (Universal Resource Identifier),URI 在 java.net.URI 中定义,显然是 Java 提供的一个类。而 Uri 位置在 android.net.Uri 中定义(Android 源码内位置:frameworks/base/core/java/android/net/Uri.java),是特有针对 Android 系统定义的类。Uri 代表要操作的数据,Android 上可用的每种资源(图像、视频片段、网页等)都可以用 Uri 来表示。

Uri 的组成部分:

  • 访问资源的命名机制(scheme)
  • 存放资源的主机名(authority)
  • 资源自身的名称,由路径表示(path)

Uri 的结构:

# 基本形式
[scheme:]scheme-specific-part[#fragment]
# 第二形式
[scheme:][//authority][path][?query][#fragment]
# 第三形式
[scheme:][//host:port][path][?query][#fragment]

特别针对scheme说明下,Uri中有这么几种常用标识:

  • content : 主要操作的是ContentProvider,它代表的是数据库中的某个资源
  • http : 某网站资源
  • file : 本地机器上的资源
  • git : git仓库中的资源
  • ftp : ftp服务器上的资源

2 Uri 的结构

2.1 基本形式

# 基本形式
[scheme:]scheme-specific-part[#fragment]

2.2 第二形式

# 第二形式
[scheme:][//authority][path][?query][#fragment]

注意其中规则:

  1. path 可以有多个,每个用 / 连接,比如:
    scheme://authority/path1/path2/path3?query#fragment
    
  2. query 参数可以带有对应的值,也可以不带,如果带对应的值用 = 表示,如:
    //这里有一个参数id,它的值是1
    scheme://authority/path1/path2/path3?id=1#fragment
    
  3. query 参数可以有多个,每个用 & 连接,如:
    /*
    	这里有3个参数:
    	参数1:id,其值是:1
    	参数2:name,其值是:pedro
    	参数3:old,没有对它赋值,所以它的值是null
    */
    scheme://authority/path1/path2/path3?id = 1&name=pedro&old#fragment
    

  在android中,除了scheme、authority是必须要有的,其它的几个path、query、fragment,它们每一个可以选择性的要或不要,但顺序不能变

2.3 第三形式

第二形式中 authority 又可以分为 host:port 的形式,这是划分最细的形式:

# 第三形式
[scheme:][//host:port][path][?query][#fragment]

2.4 例子

可以通过这个例子检测下学习效果:

http://www.pedro11.com:8080/yourpath/fileName.html?stove=10&path=32&id=4#harvic

3 Uri 的UML类图

  我把 Android 源码中 frameworks/base/core/java/android/net/Uri.java (也可在此查看:https://github.com/LineageOS/android_frameworks_base/blob/lineage-20.0/core/java/android/net/Uri.java)导入到 IDEA 工程中,通过 IDEA 的 Diagram 工具生成了它的 UML 类图(注意其中紫色方法为抽象方法),更方便分析这个有意思的类(在Uri.java中可以看出它有很多内部类,而且内部类又继承了Uri类本身)。
在这里插入图片描述
类图中各个小图标的含义可查看这里:https://jetbrains.design/intellij/resources/icons_list/

4 从 Uri 中提取 String

  • getScheme() : 获取Uri中的scheme字符串部分,即 http
  • getSchemeSpecificPart() : 获取Uri中的scheme-specific-part:部分,即 //www.pedro11.com:8080/yourpath/fileName.html
  • getFragment() : 获取Uri中的Fragment部分,即 harvic
  • getAuthority() : 获取Uri中Authority部分,即 www.pedro11.com:8080
  • getPath() : 获取Uri中path部分,即 /yourpath/fileName.html
  • getQuery() : 获取Uri中的query部分,即 stove=10&path=32&id=4
  • getHost() : 获取Authority中的Host字符串,即 www.pedro11.com
  • getPost() : 获取Authority中的Port字符串,即 8080
  • getPathSegments() : 依次提取出Path的各个部分的字符串,存入List< String>
  • getQueryParameter(String key) : 通过传进去query中某个Key的字符串,返回它对应的值
String mUriStr = "http://www.pedro11.com:8080/yourpath/fileName.html?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);
}

Log.d(tag,"getQueryParameter(\"stove\"):"+mUri.getQueryParameter("stove"));
Log.d(tag,"getQueryParameter(\"id\"):"+mUri.getQueryParameter("id"));

6 Uri操作工具类

6.1 ContentUris 处理 Uri

ContentUris 有两个作用:

  • 为路径加上ID
  • 从Uri路径中获取ID
  1. 为Uri路径加上ID: withAppendedId(uri, id)
    //比如有这样一个Uri
    Uri uri = Uri.parse("content://com.example.yy/book");
    
    //通过ContentUris的withAppendedId()方法,为该Uri加上ID  
    Uri resultUri = ContentUris.withAppendedId(uri, 10);
    
    //最后resultUri为: 
    //content://com.example.yy/book/10
    
  2. 从Uri路径中获取ID—parseId(uri)
    Uri uri = Uri.parse("content://com.example.yy/book/10")  
    long bookId= ContentUris.parseId(uri); 
    

6.2 UriMatcher 处理 Uri

待添加

6.3 uri与file、path相互转化

  1. uri 转 file
    file = new File(new URI(uri.toString()));  
    
  2. file 转 uri
    URI uri = file.toURI();  
    
  3. uri 转 path
    private String getPath(Context context, Uri uri) {  
        String path = null;
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor == null) {
            return null;
        }
        if (cursor.moveToFirst()) {
            try {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        cursor.close();
        return path;
     }
    
  4. path 转 uri
    Uri uri = Uri.parse(path);  
    
  5. file 转 path
    String path = file.getPath();  
    
  6. path 转 file
    File file = new File(path);
    

8 常用Uri

//显示网页: 
	Uri uri = Uri.parse("http://www.google.com"); 
	Intent it = new Intent(Intent.ACTION_VIEW,uri); 
	startActivity(it); 
 
//显示地图: 
	Uri uri = Uri.parse("geo:38.899533,-77.036476"); 
	Intent it = new Intent(Intent.Action_VIEW,uri); 
	startActivity(it); 
 
//路径规划: 
	Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en"); 
	Intent it = new Intent(Intent.ACTION_VIEW,URI); 
	startActivity(it); 
 
//调用拨号程序,要使用这个必须在配置文件中加入<uses-permission id="Android.permission.CALL_PHONE" /> 
	Uri uri = Uri.parse("tel:xxxxxx"); 
	Intent it = new Intent(Intent.ACTION_DIAL, uri);   
	startActivity(it);

	Uri uri = Uri.parse("tel.xxxxxx"); 
	Intent it =new Intent(Intent.ACTION_CALL,uri); 
 
//调用发送短信的程序 
	Intent it = new Intent(Intent.ACTION_VIEW); 
	it.putExtra("sms_body", "The SMS text"); 
	it.setType("vnd.android-dir/mms-sms"); 
	startActivity(it);

//发送短信 
	Uri uri = Uri.parse("smsto:0800000123"); 
	Intent it = new Intent(Intent.ACTION_SENDTO, uri); 
	it.putExtra("sms_body", "The SMS text"); 
	startActivity(it);   

//发送彩信 
	Uri uri = Uri.parse("content://media/external/images/media/23"); 
	Intent it = new Intent(Intent.ACTION_SEND); 
	it.putExtra("sms_body", "some text"); 
	it.putExtra(Intent.EXTRA_STREAM, uri); 
	it.setType("image/png"); 
	startActivity(it); 
 
//发送Email 
	Uri uri = Uri.parse("mailto:xxx@abc.com"); 
	Intent it = new Intent(Intent.ACTION_SENDTO, uri); 
	startActivity(it); 
  
	Intent it = new Intent(Intent.ACTION_SEND); 
	it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com"); 
	it.putExtra(Intent.EXTRA_TEXT, "The email body text"); 
	it.setType("text/plain"); 
	startActivity(Intent.createChooser(it, "Choose Email Client"));
  
	Intent it=new Intent(Intent.ACTION_SEND);   
	String[] tos={"me@abc.com"};   
	String[] ccs={"you@abc.com"};   
	it.putExtra(Intent.EXTRA_EMAIL, tos);   
	it.putExtra(Intent.EXTRA_CC, ccs);   
	it.putExtra(Intent.EXTRA_TEXT, "The email body text");   
	it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");   
	it.setType("message/rfc822");   
	startActivity(Intent.createChooser(it, "Choose Email Client")); 
 
//添加附件 
	Intent it = new Intent(Intent.ACTION_SEND);
	it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
	it.putExtra(Intent.EXTRA_STREAM, "[url=]file:///sdcard/mysong.mp3[/url]");
	sendIntent.setType("audio/mp3");
	startActivity(Intent.createChooser(it, "Choose Email Client"));
 
//播放多媒体 
	Intent it = new Intent(Intent.ACTION_VIEW); 
	Uri uri = Uri.parse("[url=]file:///sdcard/song.mp3[/url]"); 
	it.setDataAndType(uri, "audio/mp3"); 
	startActivity(it); 
  
	Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); 
	Intent it = new Intent(Intent.ACTION_VIEW, uri); 
	startActivity(it);   
 
//Uninstall APP
	Uri uri = Uri.fromParts("package", strPackageName, null); 
	Intent it = new Intent(Intent.ACTION_DELETE, uri); 
	startActivity(it); 
 
//调用相册 
	public static final String MIME_TYPE_IMAGE_JPEG = "image/*"; 
	public static final int ACTIVITY_GET_IMAGE = 0; 
	Intent getImage = new Intent(Intent.ACTION_GET_CONTENT); 
	getImage.addCategory(Intent.CATEGORY_OPENABLE); 
	getImage.setType(MIME_TYPE_IMAGE_JPEG); 
	startActivityForResult(getImage, ACTIVITY_GET_IMAGE); 
 
//调用系统相机应用程序,并存储拍下来的照片 
	Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
	time = Calendar.getInstance().getTimeInMillis(); 
	intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg"))); 
	startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE); 
 
//play audio 
	Uri playUri = Uri.parse("[url=]file:///sdcard/download/everything.mp3[/url]"); 
	returnIt = new Intent(Intent.ACTION_VIEW, playUri); 
 
//发送附件 
	Intent it = new Intent(Intent.ACTION_SEND);   
	it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");   
	it.putExtra(Intent.EXTRA_STREAM, "[url=]file:///sdcard/eoe.mp3[/url]");   
	sendIntent.setType("audio/mp3");   
	startActivity(Intent.createChooser(it, "Choose Email Client")); 
 
//搜索应用 
	Uri uri = Uri.parse("market://search?q=pname:pkg_name");   
	Intent it = new Intent(Intent.ACTION_VIEW, uri);   
	startActivity(it);   
 
//进入联系人页面 
	Intent intent = new Intent(); 
	intent.setAction(Intent.ACTION_VIEW); 
	intent.setData(People.CONTENT_URI); 
	startActivity(intent); 
 
//查看指定联系人 
	Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id联系人ID 
	Intent intent = new Intent(); 
	intent.setAction(Intent.ACTION_VIEW); 
	intent.setData(personUri);
	startActivity(intent); 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/649265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python 模块, 包

C# 中模块&#xff0c;就好像要using dll文件 python 中模块 就是python文件 包括类、方法、变量等 from 模块名 import 功能名 功能名() import 模块名 和 from 模块名 import * 模块名都引入了&#xff0c;但使用有所区别 import 模块名 使用 模块名.功能名 from 模块名 impo…

天天使用MySQL,你知道MySQL数据库能抗多少压力吗?附(真实案例)

今天给大家分享一个知识点&#xff0c;是关于MySQL数据库架构演进的&#xff0c;因为很多兄弟天天基于mysql做系统开发&#xff0c;但是写的系统都是那种低并发压力、小数据量的&#xff0c;所以哪怕上线了也就是这么正常跑着而已&#xff0c;但是你知道你连接的这个MySQL数据库…

关于HTTP头部的重要事项,你可能不知道的!

HTTP请求就像向服务器请求某些内容&#xff0c;而HTTP响应则是服务器的回复。就像发送一条消息并收到回复一样。 HTTP请求头部是在发出请求时包含的额外信息&#xff0c;比如你要发送的数据类型或你的身份信息。在响应头部中&#xff0c;服务器提供有关发送给你的响应的信息&am…

【大学物理实验】示波器

文章目录 选择题选择题 函数信号发生器产生的电信号调节频率和调整幅度大小的旋钮是: A. 1,2 B. 2,3 C. 3,4 D. 1,4 正确答案: D 信号输入示波器Y2通道后,示波器面板上工作方式和内触发的选择应该是: A. 工作方式选Y1,内触发选Y2 B. 工作方式选Y2,内触发选Y2 C. 工作方…

day22--哈希

两数之和 哈希表的思想 以空间换时间&#xff0c;这是由于哈希表保存了键值对&#xff0c;其查找复杂度为O(1)。 解题思路为 定义哈希表hashmap&#xff0c;其存放的键值对为<取值&#xff0c;下标>。 从开始处遍历数组&#xff0c;对于第i个位置&#xff0c;在哈希表…

【字符串part02】| 28.实现strStr()、459.重复的子字符串

目录 ✿LeetCode28.实现strStr()❀ ✿LeetCode459.重复的子字符串❀ ✿LeetCode28.实现strStr()❀ 链接&#xff1a;28.实现strStr() 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 …

C++ gets函数与strlen函数详解

引言 今天在看y总视频师对下面这串代码颇感兴趣&#xff1a; #include <iostream> #include <string.h> using namespace std; int main() {char s[1000];gets(s);int n strlen(s);for (int i 0; i < n; i){int j i;while (j < n && s[j] ! ){…

【MyBatis】什么是MyBatis?

MyBatis 是一款优秀的持久层框架&#xff0c;用于简化JDBC的开发。 说人话就是连接数据库并执行SQL的框架。 文章目录 0 JDBC简介及流程0.1 DriverManager / Connection0.2 ResultSet0.3 PreparedStatement1 SQL注入2 流程 1 MyBatis通过注解执行SQL语句1.1 MyBatis入门&…

简要介绍 | 神经辐射场(NeRF):原理、挑战与未来展望

神经辐射场(NeRF)&#xff1a;原理、挑战与未来展望 1. 背景介绍 随着深度学习和计算机图形学的不断发展&#xff0c;人工智能和图形学领域的交叉研究越来越多地受到关注。神经辐射场(NeRF)是其中一个极具潜力的研究方向&#xff0c;它结合了计算机图形学和深度学习&#xff0…

STM32驱动INMP441麦克风实现左右通道声音采集

一、参考原理图 1、INMP441 2、STM32 注意INMP441的第4引脚&#xff0c;用来选择左声道还是右声道。 二、代码生成 代码使用cubemx生成 1、iis设置 2、DMA设置 3、生成代码 三、代码修改 1、首先定义一个数组 #define BUFFER_SIZE (4)static uint32_t simpleBuf[BUFFER_S…

金属表面缺陷检测类的实践项目

【说明】&#xff1a;下面仅以Pytorch CNN Transfer Learning: Image Classifier 关于金属表面缺陷检测类的实践项目为例介绍如何创建虚拟环境以及在JuypterLab中使用对应的内核 项目已开源在https://github.com/astudent2020/Metal_Surface_Defects 提供数据集及相关代码 …

【IMDB】IMDB数据集导入PostgreSQL和join order benchmark(JOB)查询生成

目录 简述join order benchmark(JOB)查询获取IMDB导入数据到PG 简述 IMDB数据库是一个很大的&#xff0c;被广泛使用的电影&#xff0c;电视节目和演员信息的数据库&#xff0c;它包括了有关电影、电视节目、演员、制作公司、编剧、导演等信息。IMDB数据集可以为电影评论、分类…

【源码分析】Mybatis 的配置解析过程

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

Hadoop(CentOS)安装及MapReduce实现数据去重

Hadoop&#xff08;CentOS&#xff09;安装及MapReduce实现数据去重 1. JDK安装 1.1 资源下载&#xff1a; 下载地址&#xff1a;https://pan.quark.cn/s/17d7266205f9 hadoop的安装 包 java jdk安装包 eclipse连接hadoop工具 所学其他工具可自行在官网下载 centos下载地…

Verilog 高级知识点

目录 Verilog 高级知识点 1、阻塞赋值&#xff08;Blocking&#xff09; 2、非阻塞赋值&#xff08;Non-Blocking&#xff09; 3 、assign 和 always 区别 4、什么是 latch Verilog 高级知识点 本节给大家介绍一些高级的知识点。高级知识点包括阻塞赋值和非阻塞赋值、assi…

合宙Air724UG Cat.1模块硬件设计指南--ADC接口

ADC接口 简介 ADC(Analog-to-Digital Converter) 指模数转换器。是指将连续变化的模拟信号转换为离散的数字信号的器件。 合宙Cat.1模块ADC接口主要用来检测模拟电压信号量&#xff0c;用于电池电压检测&#xff0c;温湿度检测&#xff0c;TDS检测等应用。 特性 ADC精度&#…

华为OD机试真题 JavaScript 实现【素数之积】【2022Q4 100分】

一、题目描述 RSA加密算法在网络安全世界中无处不在&#xff0c;它利用了极大整数因数分解的困难度&#xff0c;数据越大&#xff0c;安全系数越高。 给定一个32位正整数&#xff0c;请对其进行因数分解&#xff0c;找出是哪两个素数的乘积。 二、输入描述 一个正整数num …

【自动文摘】BART实现finetune及evaluate

文章目录 BART介绍下游任务 fine tune BART介绍 我最近在看自动文摘相关的预训练模型&#xff0c;BART模型是2019-2020左右提出来的&#xff0c;首先介绍下它的基本情况。 论文&#xff1a;https://arxiv.org/abs/1910.13461 github&#xff1a; fairseq例子&#xff1a;http…

Efficient Global 2D-3D Matching for Camera Localization in a Large-Scale 3D Map

文章目录 Efficient Global 2D-3D Matching for Camera Localization in a Large-Scale 3D Map1. 相似源码choose_solution.pyeight_point.pyepipolar_match.py Efficient Global 2D-3D Matching for Camera Localization in a Large-Scale 3D Map 1. 相似源码 由于paper并没…

ChatGPT带火的提示工程师,构造自己的提示语

ChatGPT是一个大语言模型&#xff0c;学过全球几乎公开的大部分有效知识库&#xff0c;它什么都懂。 ChatGPT的风靡&#xff0c;爆火了一个年薪百万的提示工程师这个新就业岗位。 提示工程师&#xff0c;也就是AI训练师&#xff0c;即通过与AI交互写出相关提示&#xff0c;以帮…