Android Intent在整个Android系统使用非常广泛,如startActivity,startService,广播的发送等等都会用到Intent,以广播为例,广播的发送方sendBroadcast(Intent),那AMS是如何匹配对应的BroadcastReceiver的呢?
影响Intent匹配规则的有3个关键因素:
1.Action
2.Category
3.Data
广播接收器可以声明一个IntentFilter或者多个IntentFilter,但是只要一个IntentFilter满足要求,就可以匹配。这个同样适用于其余的组件(Activity,Service)。

IntentFilter.match

public final int match(String action, String type, String scheme,            Uri data, Set<String> categories, String logTag) {    if (action != null && !matchAction(action)) {        return NO_MATCH_ACTION;    }        int dataMatch = matchData(type, scheme, data);    if (dataMatch < 0) {         return dataMatch;    }        String categoryMismatch = matchCategories(categories);    if (categoryMismatch != null) {        return NO_MATCH_CATEGORY;    }        return dataMatch;}

在该函数中
1.如果action为空,则继续;如果action不为空,则调用matchAction,匹配Action,如果不匹配,则返回
2.调用matchData,如果返回值dataMatch大于0,则继续,否则返回
3.调用matchCategories,如果返回为空,则通过,否则不通过

从整个流程来看,影响匹配的因素就是action,data,和categories

Action匹配

public final boolean matchAction(String action) {    return hasAction(action);}public final boolean hasAction(String action) {    //如果Intent的action不为空,则其必须是IntentFilter的actions的子集    return action != null && mActions.contains(action);}

matchAction调用hasAction,在hasAction主要是判断mActions是否包含该action,mActions是一个ArrayList。IntentFilter可以通过addAction,将多个action保存在list中。

Action匹配还是比较简单的:
- 如果Intent没有action,则通过
- 如果Intent有action,filter没有action,则不通过
- 如果Intent有action,filter有action,则前者必须是后者的子集才能通过
可以用集合来概况,Intent的Action必须是IntentFilter的actions的子集,尤其针对第一点,空集是任何集合的子集,所以第一点通过。

Data匹配

Data主要包含两个部分:MIME,URI

MIME(Multipurpose Internet Mail Extensions)最早是电子邮件协议(SMTP)所规定的邮件的文件格式类型,后来逐渐被运用于其他的多种互联网协议(HTTP等)。
MIME用于指明某段数据是什么格式类型,以保证程序能够正确处理和解析

URI(Uniform resource identifier)是某种资源的全球唯一定位标志,因此多用于网络环境中,格式如下

其中scheme不仅包括了http等网络协议,还有android自定义的content来表示ContentProvider所提供的数据。host是主机的名称,port指通信端口,两者统称为Authority,如果host不存在,则port会被忽略。最后一个path是文件路径,表示该资源在host中的具体的位置

如果scheme没有指定,则authority和path都没有意义
如果scheme和authority没有指定,则path没有意义

IntentFilter没有指定MIME和URI,Intent也没有指定MIME和URI,则通过测试,否则不匹配

MIME

IntentFilter没有指定,Intent没有指定,通过;否则不通过
IntentFilter有指定,Intent没有指定MIME,则不通过;如果指定了,必须是下面5种情形才通过
1. 要么Intent的MIME要么是IntentFilter的子集
2. 要么Intent的MIME是”*/*”;
3. 要么IntentFilter的MIME是”*/*”
4. 要么IntentFilter包含”xx/*”,并且Intent的MIME斜杠前面的内容相同;
5. 要么Intent是”xx/*”,并且IntentFilter中的某个MIME匹配xx/

URI

scheme匹配

IntentFilter的schemes为空,则通过
IntentFilter的scheme不为空,
1. Intent的scheme必须不为空,并且是IntentFilter的schemes的子集
2. 如果IntentFilter存在ssp(scheme-specified part),ssp匹配,则通过
3. 如果IntentFilter与Intent的data部分ssp不匹配,则测试Authority部分,如果匹配,测试path部分,如果IntentFilter不存在path或者跟Intent匹配,则通过

SSP和Path的匹配部分同样遵循GLOB规则(见Android PatternMatcher)

categories匹配

public final String matchCategories(Set<String> categories) {    //Intent的categories为空,返回空表示匹配    if (categories == null) {        return null;    }    Iterator<String> it = categories.iterator();    //Intent的categories不为空,但是IntentFilter的mCategories为空,不匹配    if (mCategories == null) {        return it.hasNext() ? it.next() : null;    }    //Intent和IntentFilter的categories均不为空,则前者是后者的子集则匹配,否则不匹配    while (it.hasNext()) {        final String category = it.next();        if (!mCategories.contains(category)) {            return category;        }    }    return null;}
  1. 如果Intent的categories为空,则匹配
  2. 如果Intent的categories不为空,IntentFilter的categories为空,则不匹配
  3. 如果Intent的categoreis不为空,IntentFilter的categories不为空,则前者必须是后者的子集才匹配,否则不匹配

可以用集合来概况,Intent的categories必须是IntentFilter的categories的子集,尤其针对第一点,空集是任何集合的子集,所以第一点通过。跟前面的Action的匹配是一样的。

总结:

影响IntentFilter的匹配规则的有三个方面:Action,Data,Category。其中Action和Category必须满足Intent中的Action和Category必须是IntentFilter中的Action和Category的子集(空集是任何集合的子集)。Data比较复杂,Data分为MIME和Uri,如果Intent和IntentFilter均为空,则匹配,否则IntentFilter中存在的部分必须匹配。

特别的:如果Intent和IntentFilter的Action,Data,Category均为空,也是匹配的。

更多相关文章

  1. 关于Android(安卓)Studio3.2新建项目Android(安卓)resource link
  2. haproxy根据客户端浏览器进行跳转
  3. Android内容提供者源码
  4. Android(安卓)设置没有 actionBar的 样式
  5. Android(安卓)SDK与ADT不匹配的问题 This Android(安卓)SDK requ
  6. 【Android】自动提示匹配之AutoCompleteTextView
  7. android问题解答
  8. Gradle Sync Failed,报错"could not find com.android.support:ap
  9. Android(安卓)UI技巧(一)——Android中伸缩自如的9patch图片切法,没

随机推荐

  1. Android笔试题-基础
  2. LayoutInflater源码分析
  3. Android常见问题解决
  4. Android(安卓)Studio升级4.0后的编译问题
  5. Android中常用的优秀开源框架
  6. Android(安卓)滑动切换页面 以及屏幕手势
  7. android LinearGradient线性渐变
  8. Android点击通知栏信息后返回正在运行的
  9. Android实现简单加法计算器
  10. android关于时间的demo