Android IntentFilter的匹配规则

IntentFilter中的过滤信息有action,category,data

匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失败

action的匹配规则

action是一个字符串,系统预定义了一些action,同时我们也可以在应用中定义自己的action。action的匹配规则是Intent中action必须能够和过滤规则中action匹配,这里说的匹配是指action的字符串值完全一样。一个过滤规则中可以有多个action,那么只要Intent中的action能够和过滤规则中的任何一个action相同即可匹配完成。需要注意的是,Intent中如果没有指定action,那么匹配失败。总结:action的匹配要求Intent中的action存在且必须和过滤规则中的其中一个action相同。

 

category的匹配规则

category是一个字符串,系统预定义了一些category,同时我们也可以在应用中定义自己的category。category的匹配规则和action不同,它要求Intent中如果含有category,那么所有的category都必须和过滤规则中的其中一个category相同。不设置category时也可以。因为系统在startActivity或者startActivityForResult的时候会默认为Intent加上“android.intent.category.DEFAULT”这个category。所以为了我们的Activity能够接受隐式调用,必须在intent-filter中指定“android.intent.category.DEFAULT”这个category。

 

data的匹配规则

 

data的匹配规则和action类似,如果过滤规则中定义了data,那么Intent中必须定义可匹配的data。

data的结构:

android:host="string"

android:port="string"

android:path="string"

android:pathPattern="string"

android:pathPrefix="string"

android:mimeType="string"/>

data由两部分组成,mimeType和URI。mimeType指媒体类型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等不同的媒体格式。而URI中包含的数据比较多,其结构如下:

://:/[|pathPrefix>|]

实际例子如:

content://com.example.project:200/folder/

http://www.baidu.com:80/serach

scheme:URI的模式,比如http、file、content等,如果没有指定scheme,那么整个URI的其它参数无效,即URI无效

host:URI的主机,如果没有指定host,那么整个URI的其它参数无效,即URI无效

port:URI的端口号,仅当URI中指定了scheme和host时参数才有意义

path、pathPrefix、pathPattern:这三个参数表述路径信息。其中path表示完整的路径信息;pathPattern也表示完整的路径信息,但是它里面可以包含通配符“*”,“*”表示0个或者多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么“*”要写成“\\*”, "\" 要写成"\\\\";pathPrefix表示路径的前缀信息

 

1)如下过滤规则:

   

    ....

这种规则指定了媒体类型为所有类型的图片,那么Intent中的mimeType属性必须为“image/*”才能匹配,这种情况下虽然过滤规则没有指定URI,但是却有默认值,URI默认值为content和file。也就是说没有指定URI,但是Intent中的URI部分的scheme部分必须为content或者file才能匹配,为了匹配1)的规则,我们可以写出如下示例:

intent.setDataAndType(Uri.parse("file://abc"),"image/png")

另外,如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法彼此会清除对方的值,源码如下:

public @NonNull Intent setData(@Nullable Uri data) {
        mData = data;
        mType = null;
        return this;
    }

public @NonNull Intent setType(@Nullable String type) {
        mData = null;
        mType = type;
        return this;
    }

可以发现,这两个方法会清除对方的值

2)如下过滤规则

   

   

这种规则指定了两组data规则,且每个data都指定了完整的属性值,基友URI,又有mimeType。为了匹配2)中规则,我们可以写出以下示例:

intent.setDataAndType(Uri.parse("http://abc"),"video/mepg")

或者

intent.setDataAndType(Uri.parse("http://abc"),"audio/mepg")

 

通过上面两个示例,我们已经明白了data的匹配规则,关于data还有一个特殊情况需要说明,这也是它和action不同的地方,以下两种特殊的写法,它们的作用是一样的:

   

   

   

data的匹配规则就是以上这些了。

最后,当我们通过隐式启动一个Activity的时候,可以做一下判断,看是否有Activity能够匹配我们的隐式Intent,如果不做判断,匹配不到时会报Activity找不到的错误。判断方法有两种:采用PackageManager的resolveActivity方法,或者Intent的resolveActivity方法,如果它们找不到匹配的Activity就会返回null,我们通过判断返回值就可以避免找不到Activity的错误。另外PackageManager还提供queryIntentActivities方法,这个方法和resolveActivity不同的是:它不是返回最佳匹配的Activity信息,而是返回所有成功匹配的Activity信息

public abstract List queryIntentActivities(Intent intent,
            @ResolveInfoFlags int flags);

public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);

第二个参数需要注意,我们要使用MATCH_DEFAULT_ONLY这个标记位,这个标记位的含义是紧紧匹配哪些在intent-filter中声明了“android.intent.category.DEFAULT”这个category的Activity。使用这个标记位的意义在于,只要商户两个方法不会null,那么startActivity一定可以成功,如果不用这个标记位,那就把intent-filter中category不含有DEFAULT的哪些Activity给匹配出来,从而导致startActivity可能失败。以为不含有DEFAULT这个category的Activity是无法接收隐式Intent的。

 

在action和category中,有一类比较重要,他们是

             
             

这二者共同作用是用来表明这是一个入口Activity并且会出现在系统的应用列表中,少了任何一个都没有实际意义,也无法出现在系统的应用列表中,也就是二者缺一不可。

 

 

你可能感兴趣的:(android)