文章出处:http://blog.csdn.net/shift_wwx

请转载的朋友标明出处~~


前言:关于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:[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






更多相关文章

  1. android 使用statfs获得文件路径可用空间大小的方法
  2. android Uri利用及解析(文件操作)以及与路径的相互转换
  3. android 中EditView输入电话号码(3+4+4格式)
  4. Android——XML中的Bitmap资源
  5. android 5.0新特性学习--Drawable Tinting(为图片资源着色)
  6. [置顶] Android中资源文件的详解和android中的单位介绍

随机推荐

  1. 在Linux下安装Android SDK
  2. adb logcat命令查看并过滤android输出log
  3. android 上下文菜单Context Menu--折腾一
  4. Unity调用高德地图API,获取定位信息(Androi
  5. cocos2d for android 项目的部署
  6. Android 自动朗读(TTS)
  7. Android中使用 SharedPreferences
  8. 一封邮件引发的思考
  9. Android之线程阻塞(一)
  10. 《Android移动网站开发详解》