Activity 的 Flags 和 IntentFilter 匹配规则

版权声明:本文出自Jinguangyue的博客,转载必须注明出处。 http://blog.csdn.net/coderyue https://blog.csdn.net/CoderYue/article/details/79929991

Activity 的 Flags

Activity 的 Flag 标记位有很多, 比如 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_SINGLE_TOP等等, 还有的标记为可以影响 Activity 的运行状态,比如 FLAG_ACTIVITY_CLEAR_TOP 和 FLAG ACTIVITY_EXCLUDE_FROM_RECENTS等。 记录几个常用的标志位吧, 注意系统的内部使用的标记位不要去手动设置

FLAG_ACTIVITY_NEW_TASK:
为当前 Activity 指定为 SIngleTask 模式,效果和在 XML 中指定该启动模式相同。

FLAG_ACTIVITY_SINGLE_TOP:
为当前 Activity 指定为 SIngleTop 模式,效果和在 XML 中指定该启动模式相同。

FLAG_ACTIVITY_CLEAR_TOP:
具有此标记位的 Activity , 当它启动时, 在同一个任务栈中所有位于它上面的 Activity 都要出栈 ,在这种情况下, 被启动的 Activity 如果存在, 那么系统会调用它的 onNewIntent 方法,如果被启动的 Activity 采用 standerd 模式的话,那么连同它本身和它之上的 Activity 都会出栈,系统会重新创建新的 Activity 实例并且放入栈中

IntentFilter 匹配规则

Activity 的启动模式分为显示调用和隐式调用, 一般不存在同时使用2种的,如果同时使用了那么以显示调用为主, 就像广播注册, 以动态注册的优先级高, 隐式调用需要 Intent 能够匹配目标组件的 IntentFilter 中所设置的过滤信息, 如果不匹配那么将无法启动 Activity, IntentFilter 中所设置的过滤信息有 action, category, data。

为了匹配过滤列表, 需要同时匹配过滤列表中的 action, category, data 等信息, 否则匹配失败, 一个过滤列表中的 action, category, data 可以有多个, 所有的 action, category, data 分别构成不同类别, 同一个类别的信息共同约束当前类别的匹配过程, 只有一个 Intent 同时匹配 action 类别, category类别, data 类别才算完全匹配, 只有完全匹配才能成功启动目标 Activity, 另外一点, 一个 Activity 可以有多个 IntentFilter, 一个 Intent 只要能匹配任何一组 intent-filter 即可成功启动对应的 Activity。

详细匹配规则:

  1. action 的匹配规则
    action 是一个字符串, 系统也有自己的 action , 当然我们也可以自己定义 action, 只有 Intent 中的 action 和过滤规则中的 action 完全相同才可以匹配成功, 一个过滤规则中可能有多个action, 那么只要匹配其中一个即可, action 还区分大小写,大小写不同也不会匹配成功

  2. category 的匹配规则
    category 和 action 不同的是如果 Intent 中含有 category, 那么 category 都必须和过滤规则中的其中一个相同, 如果 Intent 中含有多个 category, 那么所有的 category 都必须和过滤规则中的想匹配才行, 当然 Intent 中也可以不包含 category,平时我们 start 一个 Activity都没有指定 category , 那是因为系统在启动 Activity 时候默认加了一个 category: android.intent.category.DEFAULT , 同时, 如果一个 Activity 想要被隐式调用, 那么必须为它的 IntentFilter 中指定 android.intent.category.DEFAULT 。

  3. data 的匹配规则
<data android:scheme="...“ 
          android:host="..."
          android:port="..."
          android:path="..."
          android:pathPattern="..."
          android:pathPrefix="..."
          android:mimeType="..." />

data 由2部分组成, mimeType 和 URI。 mimeTyoe 指媒体类型, 比如 image/jpeg, video/*, URI 的参数就比较多了

<scheme>://<host>:<port>/<path>

scheme: URI 的模式, 比如 http, file, content等, 如果没有指定 scheme , 那么URI无效
host: URI 主机名, 比如 com.example.project, 如果未指定, URI无效。
port: 端口号
path:完整路径信息

扫描二维码关注公众号,回复: 3223418 查看本文章

注意, Intent 中的 URI 和 MIME 类型与过滤器中指定的 URI 和 MIME 类型进行比较。 规则如下:

  1. 仅当过滤器未指定任何 URI 或 MIME 类型时,不含 URI 和 MIME 类型的 Intent 才会通过测试。
  2. 对于包含 URI 但不含 MIME 类型(既未显式声明,也无法通过 URI 推断得出)的 Intent,仅当其 URI 与过滤器的 URI 格式匹配、且过滤器同样未指定 MIME 类型时,才会通过测试。
  3. 仅当过滤器列出相同的 MIME 类型且未指定 URI 格式时,包含 MIME 类型、但不含 URI 的 Intent 才会通过测试。
  4. 仅当 MIME 类型与过滤器中列出的类型匹配时,同时包含 URI 类型和 MIME 类型(通过显式声明,或可以通过 URI 推断得出)的 Intent 才会通过测试的 MIME 类型部分。 如果 Intent 的 URI 与过滤器中的 URI 匹配,或者如果 Intent 具有 content: 或 file: URI 且过滤器未指定 URI,则 Intent 会通过测试 URI 部分检查是否匹配。 换言之,如果过滤器只是列出 MIME 类型,则假定组件支持 content: 和 file: 数据。例如
<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

另外, 如果要为 Intent 指定完整的 data, 必须调用 setDataAndType 方法, 如果分别调用 setData 和 setType 那么他们会互相清除对方的值导致调用无效,还有 Intent-filter 的匹配规则对于 service 和 BroadcastReceiver 也是同样的道理, 只不过启动 Service 一般都是显示的调用。

最后, 通过隐式方式启动 Activity 的时候可以做判断, 检查是否有 Activity 匹配,如果不做判断可能出现 ActivityNotFoundException 了, 判断方法有2种:
采用 PackageManager 的 resolveActivity 方法或者 Intent 的 resolveActivity 方法, 如果他们找不到 匹配的 Activity 就会返回 null, 这样通过判断返回值就可以规避 ActivityNotFoundException 错误了,另外 PackageManager 还提供了 queryIntentActivities(Intent intent, int flags); 他不是返回最佳匹配的 Activity 信息而是返回所有成功匹配的 Activity 信息, 这里第二个参数 flags 使用 MATCH_DEFAULT_ONLY 标记位, 这个标记位含义是仅仅匹配那些在 intent-filter 中声明 <category android:name="android.intent.category.DEFAULT"/> 这样 category 的 Activity ,使用这个标志位可以过滤掉不含 DEFAULT 的那些 Activity, 这样 startActivity 只要匹配上就能保证成功,不含有 <category android:name="android.intent.category.DEFAULT"/> 是无法接收隐式 Intent 的。

每一个应用程序都有一组这样的 action 和 category:

        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>

这2者共同作用是用来表明这是一个入口 Activity 并且会出现在系统的应用列表内, 少了任何一个都没有任何意义的。

https://developer.android.com/guide/components/intents-filters.html

猜你喜欢

转载自blog.csdn.net/CoderYue/article/details/79929991
今日推荐