<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 匹配。 但是,过滤条件与缺少 param2=value2https://project.example.com/any/path/here?param1=value1 不匹配。

“或”和“与”运算

<uri-relative-filter-group> 外的 <data> 标记会进行 OR 运算,而 <uri-relative-filter-group> 内的 <data> 标记会进行 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 #fragment 匹配,因为在评估排除规则之前就找到了匹配项,但 #fragment123 等 fragment 不匹配。

同级代码

<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" /> 匹配,而 <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>