<uri-relative-filter-group>

语法
<uri-relative-filter-group android:allow=["true" | "false"]>
  <data ... />
  ...
</uri-relative-filter-group>
包含在
<intent-filter>
可包含
<data>
说明
创建精确的 Intent 匹配规则,其中可包含 URI 查询参数和 URI 片段。这些规则可以是包含(允许)规则,也可以是排除(阻止)规则,具体取决于 android:allow 属性。匹配规则由所包含的 <data> 元素的 path*fragment*query* 属性指定。

匹配

要匹配 URI,URI 相对过滤器组的每个部分都必须与 URI 的一部分匹配。URI 中可能存在 URI 相对过滤器组中未指定的部分。例如

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="true">
    <data android:query="param1=value1" />
    <data android:query="param2=value2" />
  </uri-relative-filter-group>
  ...
</intent-filter>

此过滤器匹配 https://project.example.com/any/path/here?param1=value1&param2=value2&param3=value3,因为 URI 相对过滤器组指定的所有内容都存在。此过滤器还匹配 https://project.example.com/any/path/here?param2=value2&param1=value1,因为查询参数的顺序无关紧要。但是,此过滤器不匹配 https://project.example.com/any/path/here?param1=value1,因为它缺少 param2=value2

OR 和 AND

<data> 标签位于 <uri-relative-filter-group> 之外时是 OR 关系,而 <data> 标签位于 <uri-relative-filter-group> 之内时是 AND 关系。

请看以下示例

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <data android:pathPrefix="/prefix" />
  <data android:pathSuffix="suffix" />
  ...
</intent-filter>

该过滤器匹配以 /prefix 开头或以 suffix 结尾的路径。

相反,下一个示例匹配以 /prefix 开头且以 suffix 结尾的路径

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group>
    <data android:pathPrefix="/prefix" />
    <data android:pathSuffix="suffix" />
  </uri-relative-filter-group>
  ...
</intent-filter>

因此,同一 <uri-relative-filter-group> 中的多个 path 属性不匹配任何内容

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group>
    <data android:path="/path1" />
    <data android:path="/path2" />
  </uri-relative-filter-group>
  ...
</intent-filter>

声明顺序

请看以下示例

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group>
    <data android:fragment="fragment" />
  </uri-relative-filter-group>
  <uri-relative-filter-group android:allow="false">
    <data android:fragmentPrefix="fragment" />
  </uri-relative-filter-group>
  ...
</intent-filter>

过滤器匹配片段 #fragment,因为在评估排除规则之前找到匹配项,但像 #fragment123 这样的片段不匹配。

同级标签

<uri-relative-filter-group> 标签与其同级 <data> 标签(即位于 <uri-relative-filter-group> 之外但在同一 <intent-filter> 内的 <data> 标签)协同工作。<uri-relative-filter-group> 标签必须具有同级 <data> 标签才能正常运行,因为 URI 属性在 <intent-filter> 级别是相互依赖的

  • 如果未为 Intent 过滤器指定 scheme,则所有其他 URI 属性都将被忽略。
  • 如果未为过滤器指定 host,则 port 属性和所有 path* 属性都将被忽略。

<intent-filter><data> 子项在任何 <uri-relative-filter-group> 标签之前进行评估。然后,<uri-relative-filter-group> 标签按顺序进行评估,例如

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="false">
    <data android:path="/path" />
    <data android:query="query" />
  </uri-relative-filter-group>
  <data android:path="/path" />
  ...
</intent-filter>

过滤器接受 https://project.example.com/path?query,因为它与 <data android:path="/path" /> 匹配,后者位于 <uri-relative-filter-group> 排除规则之外。

常见用例

假设您有一个 URI https://project.example.com/path,您希望根据是否存在查询参数或查询参数的值将其匹配到 Intent。要创建匹配 https://project.example.com/path 并阻止 https://project.example.com/path?query 的 Intent 过滤器,您可以尝试类似如下的方法

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="true">
    <data android:path="/path" />
  </uri-relative-filter-group>
  ...
</intent-filter>

实际上,这不起作用。https://project.example.com/path?query URI 匹配路径 /path,并且 <uri-relative-filter-group> 标签在匹配时允许额外的部分。

修改 Intent 过滤器如下

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="false">
    <data android:path="/path" />
    <data android:queryAdvancedPattern=".+" />
  </uri-relative-filter-group>
  <uri-relative-filter-group android:allow="true">
    <data android:path="/path" />
  </uri-relative-filter-group>
  ...
</intent-filter>

此过滤器之所以有效,是因为禁止非空查询参数的阻止规则会首先进行评估。

为了简化代码,将行为反转为允许查询参数并阻止不带查询参数的 URI

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="true">
    <data android:path="/path" />
    <data android:queryAdvancedPattern=".+" />
  </uri-relative-filter-group>
  ...
</intent-filter>

URI 编码字符

要匹配包含 URI 编码字符的 URI,请在过滤器中写入原始的、未编码的字符,例如

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="true">
    <data android:query="param=value!" />
  </uri-relative-filter-group>
  ...
</intent-filter>

过滤器匹配 ?param=value! ?param=value%21

但是,如果您在过滤器中写入编码字符,如下所示

<intent-filter...>
  <data android:scheme="https" android:host="project.example.com" />
  <uri-relative-filter-group android:allow="true">
    <data android:query="param=value%21" />
  </uri-relative-filter-group>
  ...
</intent-filter>

过滤器既不匹配 ?param=value! 也不匹配 ?param=value%21

元素数量

您可以在 <intent-filter> 内放置任意数量的 <uri-relative-filter-group> 元素。

其他资源

有关 Intent 过滤器如何工作的信息,包括 Intent 对象如何与过滤器匹配的规则,请参阅Intent 和 Intent 过滤器以及Intent 过滤器

有关 <uri-relative-filter-group> 的信息,请参阅 UriRelativeFilterGroupUriRelativeFilter

属性
android:allow
此 URI 相对过滤器组是否是包含(允许)规则,而不是排除(阻止)规则。默认值为 "true"
说明
"true"(默认值) 如果 URI 相对过滤器组匹配,则 Intent 过滤器匹配
"false" 如果 URI 相对过滤器组匹配,则 Intent 过滤器不匹配
引入自
API 级别 35
另请参阅
<intent-filter>
<data>