通过Intent启动Activity有“显示启动”和“隐式启动”两种方式。显示启动需要明确指定被启动Activity的组件信息,包括包名和类名;而隐式启动不需要明确指定启动哪个Activity,只需要使用“匹配规则”描述要启动的Activity的一些特征,系统会根据这些特征搜索对应的Activity,如果对应的Activity有多个,会让用户选择要启动的Activity,否则,直接启动匹配到的Activity。
隐式启动通常用于APP之间的交互,比如,一个APP要播放音乐,但是该APP没有提供播放功能,这时该APP就可以通过隐式启动,调用当前系统中能够播放音乐的APP进行播放。下面介绍隐式启动的使用及其匹配规则。
隐式启动
隐式启动需要Intent能够匹配目标组件在intent-filter标签中设置的过滤信息,intent-filter标签中能设置的过滤信息有action、category和data三类,下面是一个过滤规则的示例:
1 | <activity |
系统对Intent进行匹配时,要同时匹配以上三类信息,才能启动目标组件。intent-filter标签中的action、category和data可以有多个,同时,一个Activity中也可以有多个intent-filter。不过,一个Intent只要匹配任何一组intent-filter即可启动对应的的Activity。
匹配规则
接下来详细分析action、category和data这三类信息的匹配规则。
action匹配规则
action是一个字符串,系统预定了一些action,可以直接使用,同时,也可以自定义action。
action的匹配规则要求Intent中的action存在,并且必须和intent-filter标签中的一个action相同。
需要注意的是action区分大小写。
category匹配规则
category也是一个字符串,系统也预定义了一些category,同样,也可以自定义category。
但是,category匹配规则与action不一样。category匹配规则要求,如果Intent中出现了category,不管有几个category,对于每个category,它必须是intent-filter标签中已经定义了的category。
需要注意的是,如果Intent没有定义category,系统在调用startActivity()和startActivityForResult()方式时,会默认为Intent加上 “android.intent.category.DEFAULT” 这个category。因此,要想Activity能够接收隐式调用,必须在其intent-filter标签中指定这个默认的category。
data匹配规则
data匹配规则和action类似,如果intent-filter标签中定义了data,那么Intent中必须要也要定义可匹配的data。
data语法格式如下所示:
1 | <data android:scheme="string" |
data由两部分组成:mimeType和URI。
mimeType指媒体类型,比如image/jpeg、audio/mpeg4-generic等,可以表示图片、文本、视频等不同的媒体格式。
URI包含了data标签中,除了mimeType以外的所有属性,下面是URI的结构及其实例:
1 | <scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>] |
URI中每项数据的含义如下:
- scheme:URI的模式,例如http、file、content等,如果URI中没有指定scheme,那么URI无效的。
- host:URI的主机名,例如www.baidu.com,如果host没有指定,URI也是无效的。
- port:URI的端口号,只有指定scheme和host参数,port参数才有意义。
- path:表示URI的路径信息。
- pathPrefix:表示URI路径的前缀信息。
- pathPattern:也可以表示路径信息,不过可以包含通配符 “*” ,用于表示0个或多个任意字符。
下面介绍两个data匹配的实例。
只配置mimeType
1 | <intent-filter> |
上面的规则指定了媒体类型为所有格式的图片类型,那么Intent中的mimeType必须指定为 “image/*” 才能匹配。这里intent-filter没有指定URI,但是系统会为其指定默认值为content和file,所以,要匹配这个过滤器,Intent中URI部分的schema还必须设置为content或者file。
因此,要匹配上面的规则,可以使用下面的示例代码:
1 | intent.setDataAndType(Uri.parse("file://abc"), "image/png"); |
配置多个data
1 | <intent-filter> |
上面的规则指定了两组data规则,如果要匹配这个规则,可以使用以下示例代码:
1 | intent.setDataAndType(Uri.parse("file://abc"), "video/mpeg"); |
或者
1 | intent.setDataAndType(Uri.parse("file://abc"), "audio/mpeg"); |
匹配规则检测
在用隐式Intent启动一个Activity的时候,可以使用resolveActivity()方法对匹配规则进行检测,如果返为null就表示该Intent无法匹配到任何Activity。
还可以使用queryIntentActivities()方法进行检测,不过,这个方法返回所有成功匹配的Activity信息,而resolveActivity()方法返回的是最佳匹配的Activity信息。
另外,Intent的匹配规则对于Service和BroadcastReceiver也是一样的,不过Android建议尽量使用显示的方式启动Service。同时,PackageManager对象也提供了类似方法去检测是否存在匹配的Service或BroadcastReceiver组件。