您的位置:首页 > 移动开发 > Android开发

android 中的Uri

2015-08-14 19:40 501 查看
文章出处: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: