我们知道,Activity
的启动模式分为两种,分别是显式启动和隐式启动。显式启动需要明确的指定被启动的对象的组件信息,包括包名和类名;而隐式启动需要Intent
能够匹配目标组件的IntentFilter
中所设置的过滤信息(原则上,一个Intent
不应该既是显式调用又是隐式调用,如果二者共存,则显示调用为主)。
IntentFilter
中的过滤信息包括 action
、category
和 data
。为了匹配过滤列表,需要同时匹配过滤列表中的action
、category
和data
信息,否则匹配失败。一个Activity
中可以有多个IntentFilter
,一个Intent
只要能匹配任何一组 intent-filter
,即可成功启动对应的Activity
。以下是一个过滤规则的实例:
action
的匹配规则
action
是一个字符串。action
的匹配规则是:Intent
中必须有一个action
且必须能够和过滤规则中的某个action
匹配(这里说的匹配是指字符串值完全一样)。
【注意】
action
中的内容是区分大小写的;
Intent
中如果没有指定action
,则视为匹配失败。
category
的匹配规则
category
是一个字符串。category
的匹配规则是:Intent
中可以没有category
,但是如果一旦有category
,不管有几个,每个都要能够和过滤规则中的任何一个category
匹配。
【注意】:如果想让Activity A
隐式启动Activity B
,那么需要在Activity B
的 intent-filter
中指定 android.intent.category.DEFAULT
这个category
,原因是系统在调用 startActivity()
或者 startActivityForResult()
方法的时候会默认为Intent
加上 android.intent.category.DEFAULT
这个category
。
data
的匹配规则
data
的匹配规则:Intent
中必须含有data
数据,并且data
数据能够完全匹配过滤规则中的某一个data
。
先来看 data
的语法格式:
data
由两部分组成: mimeType
和 URI
,URI
通过如下格式,包括scheme
、host
、port
、path
、pathPrefix
和pathPattern
。
具体的参数解释如下:
mimeType
:指媒体类型,比如 image/jpeg
、audio/mpeg4-generic
、vidio/*
等,可以表示图片、文本、视频等不同的媒体格式。
scheme
:URI
的模式,如http
、file
、content
等,如果URI
中没有指定scheme
,那么整个URI
的其他参数无效,这也意味着URI
是无效的。
host
:URI
的主机名,如www.baidu.com
,如果host
未指定,那么整个URI
中的其他参数无效,这也意味着URI
是无效的。
port
:URI
中的端口号,比如80
,进档URI
中指定了scheme
和host
参数的时候,port
参数才是有意义的。
path
:表述路径的完整信息。
pathPrefix
:表述路径的前缀信息。
pathPattern
:表述路径的完整信息,但它里面可以包含通配符*
,表示0个或任意字符(如果想要表示真是字符串,则需要转义成\\*
;\
要写成\\\\
)。
我们可以通过intent.setDataAndType(Uri.parse("URI字符串"), "mimeType字符串")
的格式为Intent
设置data
。
【注意】
URI
可以不设置,但如果设置了,则scheme
和 host
属性必须要设置;
URI
的scheme
属性有默认值,默认值为 content
或者 file
,因此,就算在intent-filter
中没有为data
设置URI
,也需要在匹配的时候设置scheme
和host
两个属性,且scheme
属性的值必须是content
或者file
;
在为Intent
指定data
的时候,必须要调用setDataAndType()
方法,不能先调用 setData()
再调用 setType()
,因为这两个方法会彼此清楚对方的值;
所有有关data
的属性可以放在同一个标签中,也可以分作多个
标签存放,其效果相同。
总结
1、以下是在JAVA
代码中匹配某个Activity
的intent-filter
的代码:
Intent intent = new Intent();
intent.addAction("my.itgungnir.action1");
intent.addCategory("my.itgungnir.category1");
intent.setDataAndType(Uri.parse("file://abc"), "text/plain");
startActivity(intent);
2、在Menifest
文件的
标签中,action
、category
和data
都可以有多个;在JAVA
代码中,一个Intent
中只能有一个action
和一个data
,可以有多个category
。
3、我们在通过隐式方式启动一个Activity的时候,可以做以下判断,看有没有Activity
能够匹配我们的Intent
,具体的判断方法有两种:
(1)使用 PackageManager
或者 Intent
的resolveActivity()
方法,这个方法会返回最佳匹配的Activity
信息,如果没有匹配的Activity
,则返回null
;
(2)使用 PackageManager
的queryIntentActivities()
方法,这个方法会返回所有成功匹配的Activity
的信息。
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
public abstract List queryIntentActivities(Intent intent, int flags);
需要说明的是这两个方法的第二个参数,我们在使用这两个方法的时候,第二个参数都必须是Intent.MATCH_DEFAULT_ONLY
,这个参数用来匹配那些在intent-filter
中声明了category
为 android.intent.category.DEFAULT
的Activity
,避免某些Activity
因为没有设置category
为DEFAULT
而无法接收隐式Intent
。
4、如果想将一个Activity
标记为应用的入口,可以在其
标签中添加如下两行属性(这两行属性必须同时存在才有用,缺一不可):