intent-filter的匹配规则
Intent有两种,一种是显式意图,一种是隐式意图。显式意图指定了具体要启动的Activity的类,所以当你打算用显式意图启动某个Activity的时候,设置intent-filter是完全没有用的。
对于每一个activity,可以有任意数量的intent-filter,在隐式意图的匹配过程当中,只要匹配上了任意一个intent-filter都能启动这个Activity。
intent-filter过滤intent根据三样东西,action,category和data。
action
action是区分大小写的字符串,一个intent-filter可以包含一个或多个action。当然,一个action都没有也是可以的,但是没有action的intent-filter是无法被成功匹配的。无论intent-filter里面有一个还是多个actions,intent的action只要和intent-filter里面这些actions有一个完全相同就行。
category
category是区分大小写的字符串,一个intent-filter可以包含任意数量的category。但是如果希望intent-filter被成功匹配,category必须至少包含"android.intent.category.DEFAULT"。category的匹配规则是intent的category一定是intent-filter里面列举的几个category之一,或者说intent的category不能超出intent-filter所列举的几个category范围之外。
data
一个intent-filter里面可以有任意数量的data,一个intent只能携带一个data(和type),我们认为,只要intent的data,完全符合intent-filter里面的任意一个data,就被认为是匹配的。
<data
android:host="sdcard"
android:mimeType="video/mp4"
android:path="/sdcard/1.MP4"
android:pathPattern=".*\\.mp4"
android:pathPrefix="/sdcard/"
android:port="-2"
android:scheme="file" />
data的结构里面主要包含了两个东西,mimeType和URI。
mimeType
mimeType是指媒体类型,是一个区分大小写的字符串。比如image/jpeg,video/mpeg等等。
URI
URI由许多元素组成,下面是URI的结构:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
具体的,比如:
file://sdcard/1.mp4
http://www.jianshu.com/p/0321f33dff7f
- scheme
例如http、content、file。 - host
URI的主机名,比如www.jianshu.com。 - port
端口号。 - path/pathPattern/pathPrefix
path表示完整的路径。pathPattern是判定完整路径是否匹配用的正则表达式。pathPrefix也是正则表达式,它匹配的是路径的前缀信息。
匹配规则
intent的data完全符合intent-filter的data,意味着
- 默认的URI
当data当中没有配置任何的关于URI的参数的时候,scheme默认为file或者content。
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/mp4" />
<data android:mimeType="image/*" />
</intent-filter>
上面的这段代码的作用是:当前的Activity可以用于打开MP4,或者是任意图片。如果你有兴趣可以去试一下,当你点击打开一张图片的时候,系统会弹出多个应用让你来选择用哪个应用来打开这张图片,这时候除了系统自带的相册,我们的应用也会赫然出现在列表中。
intent.setDataAndType(Uri.parse("file://sdcard/1.mp4"), "video/mp4");
intent.setDataAndType(Uri.parse("file://sdcard/1.jpeg"), "image/jpeg");
这是启动目标Activity的intent的配置方法。
隐式意图匹配失败的处理
隐式意图一个很大的问题就是我们并不知道系统里面是否有Activity能被匹配,比如如果你的手机里面一个查看图片的Activity都没有,那么用相应的intent隐式启动注定会失败并且抛出异常。所以在实际启动activity之前,最好是先做一下判断,比如:
intent.resolveActivity(getPackageManager());
如果返回的是null,则表示匹配失败,否则会返回最佳匹配的Activity。除此之外我们还有一种方法,可以返回所有成功匹配的Activity,像这样:
getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
getPackageManager().queryIntentActivities(intent, PackageManager.GET_INTENT_FILTERS);
getPackageManager().queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER);
最后说一下一类特殊的intent-filter
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
它们组合出现代表程序会出现在系统的应用列表中,单独出现没有任何意义。如果想获得所有出现在应用列表中的应用,那么可以定义一个intent,用queryIntentActivities来获取到匹配的所有Activit