文章出处:http://blog.csdn.net/shift_wwx/article/details/47663373
请转载的朋友标明出处~~
前言:关于Uri网上相关的例子还是很多的,但是结合source code来讲解的很少,个人还是习惯性根据source code 总结一下。
总结版本基于4.4
一、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:admin@3gstdy.com
#寻找某个应用
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:nobody@google.com". 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语法:[userinfo@]host[:port]
3)fragment:第一次出现 ‘#’ 之后的string