我们知道,启动Activity分为两种,显示调用和隐式调用,二者的区别在这里就不多说了,显示调用需要明确的指定被启动对象的组件信息,包括报名和类名。而隐式调用则不需要,原则上一个Intent不应该既是显示调用又是隐式调用,如果二者共存的话,以显示调用为主。显示调用很简单,这里主要介绍一下隐式调用。隐式调用需要Intent匹配目标组件的IntentFilter中设置的过滤信息,如果不匹配则无法启动Activity。IntentFilter中的过滤信息有action,category,data,下面是一个过滤规则的示例
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.example.xuelinlin.retrofitdemo"/>
<action android:name="com.example.xuelinlin.c1"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="com.example.xuelinlin.category.c"/>
<category android:name="com.example.xuelinlin.category.d"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
为了匹配过滤列表中的信息,需要匹配 action ,category , data ,只有一个Intent同时匹配 类别action,类别 category,类别data,才能成功启动目标Activity,另外,一个Activity可以有多组Intent-filter,只要能匹配其中一组Intent-filter,就能成功启动目标Activity,如下所示
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.example.xuelinlin.retrofitdemo"/>
<action android:name="com.example.xuelinlin.c1"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="com.example.xuelinlin.category.c"/>
<category android:name="com.example.xuelinlin.category.d"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.SELECTED_ALTERNATIVE"></category>
<data android:mimeType="image/*"/>
<data android:mimeType="video"/>
</intent-filter>
</activity>
下面详细介绍各个属性的匹配规则
1. action 的匹配规则
action是一个字符串,系统化预定义了一些action,我们也可以在应用中自己定义一些action,action的匹配规则是Intent的action必须和过滤规则中的action信息完全一致,才算匹配成功,过滤规则中可能会有多个action,只要和其中一个action匹配成功,就算匹配成功了,如果Intent中没有知道action,那么匹配总是失败,总结一下,action必须指定,必须和过滤规则中的其中一个aciton相同,而且action是区分大小写的,大小写不同,会匹配失败。
2. category 的匹配规则
category是一个字符串,系统预定义了一些category,我们也可以在应用中自己定义一些 category,category的匹配规则和action不同,它要求Intent中如果含有category,那么必须所有的category都要和过滤规则的中的一个category相同,换句话说,如果Intent中指定了category,那么几个category中,每个category都必须是过滤规则中定义了的category的其中一个,当然,Intent中可以没有category,如果没有category的话,按照上面的描述,仍然可以匹配成功,注意这里和action的匹配规则不同,action要求Intent中必须有,而且其中一个必须要和过滤规则中的action相同。为什么不设置category 可以匹配成功呢,原因是系统调用startActivity或者startActivityForResult的时候,会默认为Intent加上”android.intent.category.LAUNCHER“这个category,所以这个category就可以匹配前面过滤规则中的“android.intent.category.LAUNCHER”。同时,为了我们的Activity能够接受隐式调用,必须在intent-filter中指定“android.intent.category.LAUNCHER“这个category。
3. data的匹配规则
data 的匹配规则和action类似,那么Intent中必须也要定义可匹配的data。在介绍data之前,我们先了解一下data的结构,因为data稍微有些复杂。
<data android:mimeType="string"
android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
/>
下面介绍一下每个数据的含义:
Scheme :URI模式,比如file,http,content等,如果URI中没有指定scheme,那么整个URI的其他参数也是无效的,这也意味着URI是无效的。
Host: URI的主机名,比如 www.baidu.com,如果host未指定,那么整个URI的其他参数也是无效的,这也意味着URI是无效的。
Port: URI的端口号, 比如 80, 仅当URI中指定了scheme和host参数时,port参数才是有效的。
Path,PathPattern,PathPrefix:这三个参数表述路径信息,其中path表示完整的路径,pathPattern也表示完整的路径,但是它里面可以包含通配符” * “ ,* 表示0个或多个任意字符;PathPrefix表示路径的前缀信息。
下面说一下data 的匹配规则,下面分情况说明。
(1) 如下 过滤规则:
<intent-filter>
<data android:mimeType="image/*"/>
...
</intent-filter>
这种规则就指定了媒体类型为所有类型的图片,为了匹配上面的规则,我们可以写出如下示例:
i.setDataAndType(Uri.parse("file://abc"),"image/png");
另外,如果要为Intent指定完整的data,必须要调用setDataAndTyp方法,不能先调用setData,在调用setType,因为这两个方法会清除彼此的值,这个看源码就很容易理解了。
(2)如下过滤规则:
<intent-filter>
<data android:mimeType="video/mpeg" android:scheme="http" ... />
<data android:mimeType="audio/mpeg" android:scheme="http" ... />
...
</intent-filter>
这种规则指定了两组完整的属性值,既有URI,又有mimeType,为了匹配上面的规则,我们可以写出如下示例:
i.setDataAndType(Uri.parse("http://abc"),"video/mpeg");
或者
i.setDataAndType(Uri.parse("http://abc"),"audio/mpeg");
通过上面两个示例,读者应该大概已经明白了data的匹配规则了吧。
在action 和category中,有一类action 和 category是比较重要的,他们是
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
这二者共同作用是用来标明这个入口Activity,并且会出现在系统的应用列表中,少了任何一个都没有意义,也无法出现在系统的应用列表中,也就是二者缺一不可。