IntentFilter匹配规则

Activity的启动方式分为两种:

  • 显式启动 通过指明启动的Activity类
  • 隐式启动 通过Intent匹配目标组件的IntentFilter中设置的信息。如果不匹配,就无法启动目标Activity。

隐式启动中IntentFilter的作用

IntentFilter主要包括 : action category data。只有Intent完全匹配三者,才能成功启动Activity。一个Activity可以拥有多个IntentFilter,一个Intent只要能匹配其中一个,就能成功启动Activity。

<activity android:name=".MyActivity">
    <intent-filter>
        <action android:name="com.me.my_activity" />
        <categoriey android:name="com.me.my_category" />
        <categoriey android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

action 匹配规则

actioin 根据name属性值进行匹配。Intent的 action 需要与 name 的值完全一样,才算匹配成功。一个 IntentFilter 可以有多个 action , Intent 的 action 只要和其中一个action匹配成功就可以。一个Intent如果没有指定action,那么匹配失败。

category 匹配规则

category根据name属性值进行匹配。Intent要么不携带 category 参数,直接默认匹配。要么携带的 category 每一个都必须在 IntentFilter 中的 category 能匹配到。 Intent 不携带category也能匹配成功是因为 : 调用startActivitystartActivityForResult时,系统会默认为Intent添加<category android:name="android.intent.category.DEFAULT" />category。所以想要Activity能接受隐式调用,就必须给Activity指定<category android:name="android.intent.category.DEFAULT" />这个category。

data 匹配规则

data的匹配和action类似,也是只要Intent的data能匹配多个data中的一个就匹配成功。

data 由两部分组成 : URI

  • mineType 媒体类型。比如image/* video/*。可以表示图片,文本,视频等不同媒体格式。
  • URI

URI的结构

<scheme>://<host>:<port>/[<[path]>|[pathPrefix]|[pathPattern]]

  • scheme : URI的模式,比如http file content等。如果Intent的URI中没有指定scheme,那么整个URI的其他参数无效,这个URI也就无效。过滤规则中的scheme默认需要匹配contentfile
  • host : URI的主机名。比如www.mm.com。如果Intent的URI中没有指定host,那么整个URI的其他参数无效,这个URI也就无效。
  • port : URI的端口号。只有Intent的URI中指定了scheme和port参数时才有意义。
  • path pathPattern pathPrefix : 表示路径信息
    • path 完整路径。
    • pathPattern 完成路径。可以包含通配符*,表示0个或多个任意字符
    • pathProfix 路径的前缀信息。

实例1

<intent-filter>
	......	
    <data android:mimeType="image/*" />
</intent-filter>

Intent中的mimeType必须是image/*才能匹配。这里的过滤规则虽然没有指定URI,但是scheme默认为contenefile

只设置mimeType的intent.setType("image/*")将不能匹配。 需要同时设置 :

intent.setDataAndType(Uri.parse("file://xxx"), "image/*");

intent.setType和intent.setData不能分开调用,因为两者都会清空彼此的信息

从Android源码中可以看到 :

public Intent setData(Uri data) {
	mData = data;
	mType = null;
	return this;
}
public Intent setType(String type) {
    mData = null;
    mType = type;
	return this;
}

实例2

<intent-filter>
	......
    <data
        android:mimeType="image/jpeg"
        android:scheme="http" />
    <data
        android:mimeType="video/mpeg"
        android:scheme="http" />
</intent-filter>

这个data规则

intent.setDataAndType(Uri.parse("http://xxx"),"image/jpeg");

或者

intent.setDataAndType(Uri.parse("http://zzz"),"video/mpeg");

都可以匹配。

data的属性可以同行写,也可以分开下。

<data
    android:host="www.xxx.com"
    android:mimeType="image/*"
    android:scheme="http" />
-------------------------------------
<data android:host="www.xxx.com" />
<data android:scheme="http" />
<data android:mimeType="image/*" />

Android的其他组件,Service BroadcastReceiver的IntentFiler匹配规则和Activity的类似。

  • 当隐式启动一个Activity时,可以使用Intent的resolveActivity(PackageManager pm)方法判断是否有匹配的activity。
  • 也可以调用PackageManager的resolveActivity(Intent itent,int flag)方法判断。

    • 第二个参数 flag 作为匹配的选项。一般使用MATCH_DEFAULT_ONLY参数。
    • MATCH_DEFAULT_ONLY 只匹配 intent-filter 中声明了<category android:name="android.intent.category.DEFAULT" />的Activity。因为没有声明这个category的Activity不能隐式调用。

      if (intent.resolveActivity(getPackageManager()) == null) {
      	//证明没有对应的activity
      }