前言
众所周知,Activity的启动模式有两种,分为显示启动和隐式启动。显示启动很简单,就是根据指定被启动对象的组件信息:包括包名和类名;隐式启动需要根据Intent能够匹配的目标组件来启动,如果匹配不到就无法启动Activity。
IntentFilter
IntentFilter
中的过滤信息有action、category、data。这三个属性需要同时匹配才能算匹配成功,才能启动目标Activity。一个过滤列表中的action、category、data可以有多个,所有的action、category、data分别构成不同类别,同一类别信息共同约束当前类别匹配过程。一个Activity中可以有多个intent-filter,一个Intent只要能够匹配任何一组intent-filter就可以启动Activity。
action的匹配规则
action是一个字符串,系统预定义了一些action,我们也可以在应用中自己定义自己的action,action的匹配规则是Intent中的action必须能够和过滤规则中的任何一个action相同,注意如果Intent中如果没有指定action,那么匹配失败,action区分大小写,大小写不同字符串相同的action会匹配失败
category的匹配规则
category也是一个字符串,系统预定义了一些category,我们也可以自定义。category的过滤规则是Intent中如果有category,不管有几个每个都要和过滤规则中的任何一个category相同;如果没有category也可以,因为系统在调用startActivity
或者startActivityForResult
的时候会默认为Intent加上"android.intent.category.DEFAULT"
这个category。为了让activity能够接受隐式调用,必须在intent-filter中指定
<category android:name="android.intent.category.DEFAULT" />
data的匹配规则
和action的匹配规则一样,如果过滤规则定义了data,那么Intent中也要定义可匹配的data。data由两部分组成,mimeType和URI。
mimeType指媒体类型,比如image/jpeg、text/plain、video/*等,可以表示图片、文本、视频等不同的媒体格式。
URI包括scheme、host、port 和path四个部分,host和port合起来也成authority(host:port)部分
1.Scheme: URI 的模式,比如 http,file,content,如果URI没有指定Scheme,那么整个URI的其他参数无效,也就意味着URI无效;
2.Host:URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI的其他参数无效,也就意味着URI无效;
3.Port:URI的端口号,比如80,仅当URI中制定了scheme和host参数的时候port参数才有意义。
4.Path:路径。
接下来开始介绍data的过滤规则,下面分情况说明
情况一:data规则不完整。如下所示
<intent-filter>
<data android:mimeType="image/*"/>
</intent-filter>
这种规则指定了媒体类型为所有类型的图片,那么intent中的mimeType属性必须为“image/*”才能匹配成功,这种情况虽然没有指定URI,但intent中的URL部分的schema默认值为content和file。也就是说虽然没有指定URI,但是intent中的URI部分的schema必须为content或者file才能匹配成功,这点尤其需要注意。
情况二:定义了多组data规则,并且每个data都定义了完整属性,既有URI又有mimeType。如下所示
<intent-filter>
<data android:mimeType="video/mpeg" android:scheme="http" ... />
<data android:mimeType="audio/mpeg" android:scheme="http" ... />
</intent-filter>
为了匹配这种intent filter,我们也需要在intent中完整定义其中一组data规则才能匹配成功。另外,如果要为intent指定完整的data,必须调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法彼此会清除对方的值。
URI有默认值Scheme为content或file,如果过滤列表中未定义Scheme,在Intent用http的话会报错。
最后,当我们隐式启动Activity时候,应该做一下判断,看Activity是否能够匹配我们的隐式Intent,如果不做判断不匹配的话就会报错。可以用resolveActivity判断