安卓rom源码分析程序员

intent-filter的匹配规则

2016-04-05  本文已影响1278人  吴晨

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

匹配规则

intent的data完全符合intent-filter的data,意味着

<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

上一篇下一篇

猜你喜欢

热点阅读