android 中的Uri
文章出处:http://blog.csdn.net/shift_wwx
请转载的朋友标明出处~~
前言:关于Uri网上相关的例子还是很多的,但是结合source code来讲解的很少,个人还是习惯性根据source code 总结一下。
一、source code(frameworks/base/core/java/android/net/Uri.java)
public abstract class Uri implements Parcelable, Comparable<Uri> { private Uri() {} public abstract boolean isHierarchical(); public boolean isOpaque() { return !isHierarchical(); } public abstract boolean isRelative(); public boolean isAbsolute() { return !isRelative(); } public abstract String getScheme(); public abstract String getSchemeSpecificPart(); public abstract String getEncodedSchemeSpecificPart(); public abstract String getAuthority(); public abstract String getEncodedAuthority(); public abstract String getUserInfo(); public abstract String getEncodedUserInfo(); public abstract String getHost(); public abstract int getPort(); public abstract String getPath(); public abstract String getEncodedPath(); public abstract String getQuery(); public abstract String getEncodedQuery(); public abstract String getFragment(); public abstract String getEncodedFragment(); public abstract List<String> getPathSegments(); public abstract String getLastPathSegment(); public boolean equals(Object o) { if (!(o instanceof Uri)) { return false; } Uri other = (Uri) o; return toString().equals(other.toString()); } public int hashCode() { return toString().hashCode(); } public int compareTo(Uri other) { return toString().compareTo(other.toString()); } public abstract String toString(); public String toSafeString() { String scheme = getScheme(); String ssp = getSchemeSpecificPart(); if (scheme != null) { if (scheme.equalsIgnoreCase("tel") || scheme.equalsIgnoreCase("sip") || scheme.equalsIgnoreCase("sms") || scheme.equalsIgnoreCase("smsto") || scheme.equalsIgnoreCase("mailto")) { StringBuilder builder = new StringBuilder(64); builder.append(scheme); builder.append(':'); if (ssp != null) { for (int i=0; i<ssp.length(); i++) { char c = ssp.charAt(i); if (c == '-' || c == '@' || c == '.') { builder.append(c); } else { builder.append('x'); } } } return builder.toString(); } } // Not a sensitive scheme, but let's still be conservative about // the data we include -- only the ssp, not the query params or // fragment, because those can often have sensitive info. StringBuilder builder = new StringBuilder(64); if (scheme != null) { builder.append(scheme); builder.append(':'); } if (ssp != null) { builder.append(ssp); } return builder.toString(); } public abstract Builder buildUpon(); /** Index of a component which was not found. */ private final static int NOT_FOUND = -1; /** Placeholder value for an index which hasn't been calculated yet. */ private final static int NOT_CALCULATED = -2; private static final String NOT_HIERARCHICAL = "This isn't a hierarchical URI."; /** Default encoding. */ private static final String DEFAULT_ENCODING = "UTF-8"; /** * Creates a Uri which parses the given encoded URI string. * * @param uriString an RFC 2396-compliant, encoded URI * @throws NullPointerException if uriString is null * @return Uri for this given uri string */ public static Uri parse(String uriString) { return new StringUri(uriString); } /** * Creates a Uri from a file. The URI has the form * "file://<absolute path>". Encodes path characters with the exception of * '/'. * * <p>Example: "file:///tmp/android.txt" * * @throws NullPointerException if file is null * @return a Uri for the given file */ public static Uri fromFile(File file) { if (file == null) { throw new NullPointerException("file"); } PathPart path = PathPart.fromDecoded(file.getAbsolutePath()); return new HierarchicalUri( "file", Part.EMPTY, path, Part.NULL, Part.NULL); } ...... }1、什么是Uri
Uri就是Android系统为了特殊需要,而制定的一种拥有特殊格式的一种数据模式。
从注释看:
The "four main components" of a hierarchical URI consist of <scheme>://<authority><path>?<query>就是说hierarchical 格式的Uri分为四部分:
1)scheme:访问资源的命名机制,通过这个可以获悉Uri 的具体资源存在形式,如http、content、file、market等
2)authority:存放资源的主机名,例如Provider 里面会对资源进行操作、存放,这个时候Provider就需要指出authority。
对于Provider 具体可以看一下:《Android基础总结之八:ContentProvider详解》
authority 应该是scheme:// 之后到第一次出现 ‘/’ 或‘?’ 或‘#’之间的string
3)path:authority之后第一个 ‘/’ 开始到 ‘?’ 或 ‘#’ 之前的string(包含'/')
4)query:'?' 号之后 '#' 号之前的string
经常看到的Uri形式有:
#打开一个网页http://blog.3gstdy.com/#打开地图并定位到一个点geo:52.76,-79.0342#拨打电话tel:10086#播放音频文件file:///sdcard/download/everything.mp3#打开发邮件界面mailto:[email protected]#寻找某个应用market://search?q=pname:pkg_name#路径规划http://maps.google .com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en
2、getScheme、getSchemeSpecificPart、getEncodedSchemeSpecificPart
1)getScheme:返回scheme,如果Uri是相对路径,那么就返回null
2)getSchemeSpecificPart :这里出现了ssp 概念,从这里可以将Uri 重新格式化为:
[scheme:]schemeSpecificPart[#fragment] ([...]表示可选)如果是个相对路径的话,就返回整个。
3)getEncodedSchemeSpecificPart:如果ssp里面有出现非A~Z、a~z、0~9、‘_’、‘-’、‘叹号’、‘点号’、‘~’、‘单引号’、‘(’、‘)’、‘星号’,都需要encode一把,有时候会看到%连接的一串,那都是encode。
详细的可以看一下source code:
for (int i = 0; i < bytesLength; i++) { encoded.append('%'); encoded.append(HEX_DIGITS[(bytes[i] & 0xf0) >> 4]); encoded.append(HEX_DIGITS[bytes[i] & 0xf]);}后面相关encode都是这样的,具体实现情况看函数:
String encode(String s, String allow)
3、isRelative、isAbsolute
isRelative:就是没有明确的scheme
isAbsolute:非isRelative
public boolean isAbsolute() { return !isRelative(); }4、分层、不透明
/** * Returns true if this URI is hierarchical like "http://google.com". * Absolute URIs are hierarchical if the scheme-specific part starts with * a '/'. Relative URIs are always hierarchical. */ public abstract boolean isHierarchical(); /** * Returns true if this URI is opaque like "mailto:[email protected]". The * scheme-specific part of an opaque URI cannot start with a '/'. */ public boolean isOpaque() { return !isHierarchical(); }不透明也就是不分层。
通过注释可以大概理解两api 的意义:
如果ssp开头是 ‘/’,那么就是hierarchical,如果不是就是opaque。
当然,通过source code也能够确定的:
public boolean isHierarchical() { int ssi = findSchemeSeparator(); if (ssi == NOT_FOUND) { // All relative URIs are hierarchical. return true; } if (uriString.length() == ssi + 1) { // No ssp. return false; } // If the ssp starts with a '/', this is hierarchical. return uriString.charAt(ssi + 1) == '/';}5、getHost()、getPort()
1)getHost:authority 中 ‘@’ 之后到 ‘:’ 之前的string
2)getPort:authority 中 ‘:’ 之后的 integer
6、Uri是个abstract类,好多函数是abstract的,肯定是有地方实现的。
那么Uri是abstract类,并不能实例化,应用的时候是怎么使用这些method,提供了两种方法:
public static Uri parse(String uriString) { return new StringUri(uriString); }
public static Uri fromFile(File file) { if (file == null) { throw new NullPointerException("file"); } PathPart path = PathPart.fromDecoded(file.getAbsolutePath()); return new HierarchicalUri( "file", Part.EMPTY, path, Part.NULL, Part.NULL); }显然是在这里new 出来了,返回的类型都是Uri,可以确定StringUri 和 HierarchicalUri都是Uri的子类了。
总结:
根据之前的解释可以清楚知道Uri 的格式:
scheme:ssp#fragment
1)scheme 就是第一个 ‘:’ 之前的部分,没有的就返回null
2)ssp:authority + path + query
当然其中的部分可能不存在,反正ssp就是这三部分的统称
ssp 语法:[//aurhority][path][?query]
authority 也可能包含了userinfo + host + port
authority语法:[[email protected]]host[:port]
3)fragment:第一次出现 ‘#’ 之后的string
更多相关文章
- android 使用statfs获得文件路径可用空间大小的方法
- android Uri利用及解析(文件操作)以及与路径的相互转换
- android 中EditView输入电话号码(3+4+4格式)
- Android——XML中的Bitmap资源
- android 5.0新特性学习--Drawable Tinting(为图片资源着色)
- [置顶] Android中资源文件的详解和android中的单位介绍