关于Intent Uri

2,524 阅读2分钟

Intent Uri 的组成部分

intent Uri 以 intent:// 开头,以 end结尾 ,主要分为以下几个部分,每个部分之间通过 ; 进行分隔。

  • intent://{data}#Intent Intent中的data Uri的配置
  • scheme Intent 中{data}的协议
  • action Intent的action
  • type Intent的类型
  • launchFlags 启动Intent时的flag
  • package Intent携带的程序的包名,用于设置要打开哪个程序
  • component Intent携带的组件名(组件包名/组件名),用于设置要打开程序的某个界面
  • extras Intent携带的其他字段
  • end Intent Uri的结束标记

Intent Uri 的解析

Intent Uri 通过Android中的 Intent#parseUri(String uri, @UriFlags int flags) 进行解析,返回 Intent 实例对象。

  • intent://{data}#Intentscheme 部分会被解析成 Intent 的 mData 字段。可通过 Intent.getData() 方法获取。

  • action 部分会被解析成 Intent 的 mAction 字段。可通过 Intent.getAction() 方法获取。

  • type 部分会被解析成 Intent 的 mType 字段。可通过 Intent.getType() 方法获取。

  • launchFlags 部分会被解析成 Intent 的 mFlags 字段。可通过 Intent.getFlags() 方法获取。

  • pacakge 部分会被解析成 Intent 的 mPackage 字段。可通过 Intent.getPackage() 方法获取。

  • component 部分会被解析成 Intent 的 mComponent 字段。可通过 Intent.getComponent() 方法获取。

  • extras 部分会被解析成 Intent的 mExtras 字段。可通过 Intent.getExtras() 方法获取。 extra 使用以下字符串开头(表示extra字段的类型),然后加上 {key}={value}, extra 之间也使用 ; 分隔。

    • S. String类型
    • B. Boolean类型
    • b. Byte类型
    • c. char类型
    • d. Double类型
    • f. Float类型
    • i. Integer类型
    • l. Long类型
    • s. Shor类型

示例

intent:#Intent;action=your.example.namespace.CUSTOMACTION;package=your.example.namespace;component=your.example.namespace/.YourActivity;S.extraValueName=WOW;end

intent://intent_data_uri#Intent;scheme=novelx;action=jump.novel;type=plugin;component=net.sourceforge.simcpux/.MainActivity;i.param2=22323;S.url=http%3A%2F%2Fbaidu.com;S.parm1=str_1;end

Intent

public static Intent parseUri(String uri, @UriFlags int flags) throws URISyntaxException {
        int i = 0;
        try {
            final boolean androidApp = uri.startsWith("android-app:");

            // Validate intent scheme if requested.
            if ((flags&(URI_INTENT_SCHEME|URI_ANDROID_APP_SCHEME)) != 0) {
                if (!uri.startsWith("intent:") && !androidApp) {
                    Intent intent = new Intent(ACTION_VIEW);
                    try {
                        intent.setData(Uri.parse(uri));
                    } catch (IllegalArgumentException e) {
                        throw new URISyntaxException(uri, e.getMessage());
                    }
                    return intent;
                }
            }

            i = uri.lastIndexOf("#");
            // simple case
            if (i == -1) {
                if (!androidApp) {
                    return new Intent(ACTION_VIEW, Uri.parse(uri));
                }

            // old format Intent URI
            } else if (!uri.startsWith("#Intent;", i)) {
                if (!androidApp) {
                    return getIntentOld(uri, flags);
                } else {
                    i = -1;
                }
            }

            // new format
            Intent intent = new Intent(ACTION_VIEW);
            Intent baseIntent = intent;
            boolean explicitAction = false;
            boolean inSelector = false;

            // fetch data part, if present
            String scheme = null;
            String data;
            if (i >= 0) {
                data = uri.substring(0, i);
                i += 8; // length of "#Intent;"
            } else {
                data = uri;
            }

            // loop over contents of Intent, all name=value;
            while (i >= 0 && !uri.startsWith("end", i)) {
                int eq = uri.indexOf('=', i);
                if (eq < 0) eq = i-1;
                int semi = uri.indexOf(';', i);
                String value = eq < semi ? Uri.decode(uri.substring(eq + 1, semi)) : "";

                // action
                if (uri.startsWith("action=", i)) {
                    intent.setAction(value);
                    if (!inSelector) {
                        explicitAction = true;
                    }
                }

                // categories
                else if (uri.startsWith("category=", i)) {
                    intent.addCategory(value);
                }

                // type
                else if (uri.startsWith("type=", i)) {
                    intent.mType = value;
                }

                // identifier
                else if (uri.startsWith("identifier=", i)) {
                    intent.mIdentifier = value;
                }

                // launch flags
                else if (uri.startsWith("launchFlags=", i)) {
                    intent.mFlags = Integer.decode(value).intValue();
                    if ((flags& URI_ALLOW_UNSAFE) == 0) {
                        intent.mFlags &= ~IMMUTABLE_FLAGS;
                    }
                }

                // package
                else if (uri.startsWith("package=", i)) {
                    intent.mPackage = value;
                }

                // component
                else if (uri.startsWith("component=", i)) {
                    intent.mComponent = ComponentName.unflattenFromString(value);
                }

                // scheme
                else if (uri.startsWith("scheme=", i)) {
                    if (inSelector) {
                        intent.mData = Uri.parse(value + ":");
                    } else {
                        scheme = value;
                    }
                }

                // source bounds
                else if (uri.startsWith("sourceBounds=", i)) {
                    intent.mSourceBounds = Rect.unflattenFromString(value);
                }

                // selector
                else if (semi == (i+3) && uri.startsWith("SEL", i)) {
                    intent = new Intent();
                    inSelector = true;
                }

                // extra
                else {
                    String key = Uri.decode(uri.substring(i + 2, eq));
                    // create Bundle if it doesn't already exist
                    if (intent.mExtras == null) intent.mExtras = new Bundle();
                    Bundle b = intent.mExtras;
                    // add EXTRA
                    if      (uri.startsWith("S.", i)) b.putString(key, value);
                    else if (uri.startsWith("B.", i)) b.putBoolean(key, Boolean.parseBoolean(value));
                    else if (uri.startsWith("b.", i)) b.putByte(key, Byte.parseByte(value));
                    else if (uri.startsWith("c.", i)) b.putChar(key, value.charAt(0));
                    else if (uri.startsWith("d.", i)) b.putDouble(key, Double.parseDouble(value));
                    else if (uri.startsWith("f.", i)) b.putFloat(key, Float.parseFloat(value));
                    else if (uri.startsWith("i.", i)) b.putInt(key, Integer.parseInt(value));
                    else if (uri.startsWith("l.", i)) b.putLong(key, Long.parseLong(value));
                    else if (uri.startsWith("s.", i)) b.putShort(key, Short.parseShort(value));
                    else throw new URISyntaxException(uri, "unknown EXTRA type", i);
                }

                // move to the next item
                i = semi + 1;
            }

            if (inSelector) {
                // The Intent had a selector; fix it up.
                if (baseIntent.mPackage == null) {
                    baseIntent.setSelector(intent);
                }
                intent = baseIntent;
            }

            if (data != null) {
                if (data.startsWith("intent:")) {
                    data = data.substring(7);
                    if (scheme != null) {
                        data = scheme + ':' + data;
                    }
                } else if (data.startsWith("android-app:")) {
                    if (data.charAt(12) == '/' && data.charAt(13) == '/') {
                        // Correctly formed android-app, first part is package name.
                        int end = data.indexOf('/', 14);
                        if (end < 0) {
                            // All we have is a package name.
                            intent.mPackage = data.substring(14);
                            if (!explicitAction) {
                                intent.setAction(ACTION_MAIN);
                            }
                            data = "";
                        } else {
                            // Target the Intent at the given package name always.
                            String authority = null;
                            intent.mPackage = data.substring(14, end);
                            int newEnd;
                            if ((end+1) < data.length()) {
                                if ((newEnd=data.indexOf('/', end+1)) >= 0) {
                                    // Found a scheme, remember it.
                                    scheme = data.substring(end+1, newEnd);
                                    end = newEnd;
                                    if (end < data.length() && (newEnd=data.indexOf('/', end+1)) >= 0) {
                                        // Found a authority, remember it.
                                        authority = data.substring(end+1, newEnd);
                                        end = newEnd;
                                    }
                                } else {
                                    // All we have is a scheme.
                                    scheme = data.substring(end+1);
                                }
                            }
                            if (scheme == null) {
                                // If there was no scheme, then this just targets the package.
                                if (!explicitAction) {
                                    intent.setAction(ACTION_MAIN);
                                }
                                data = "";
                            } else if (authority == null) {
                                data = scheme + ":";
                            } else {
                                data = scheme + "://" + authority + data.substring(end);
                            }
                        }
                    } else {
                        data = "";
                    }
                }

                if (data.length() > 0) {
                    try {
                        intent.mData = Uri.parse(data);
                    } catch (IllegalArgumentException e) {
                        throw new URISyntaxException(uri, e.getMessage());
                    }
                }
            }

            return intent;

        } catch (IndexOutOfBoundsException e) {
            throw new URISyntaxException(uri, "illegal Intent URI format", i);
        }
    }