前言
在Android开发中,启动Activity分为两种方式,显式调用和隐式调用.显式调用很简单,只需要目标Activity的包名和类名.而隐式调用需要Intent能够匹配目标组件的IntentFilter所配置的过滤信息.
Intent过滤信息中有action, category, data.下面是一个Activity的过滤规则实例:
<activity android:name=".FilterExampleActivity">
<intent-filter>
<action android:name="me.jesse.www.action1"></action>
<action android:name="me.jesse.www.action2"></action>
<category android:name="me.jesse.www.category1"></category>
<category android:name="me.jesse.www.category2"></category>
<data android:mimeType="text/plain"></data>
</intent-filter>
</activity>
怎么才算匹配?
只有一个Intent同时匹配action类别, category类别, data类别才算完全匹配.只有完全
匹配才能启动目标Activity.一个Activity可以配置多组IntentFilter.一个Intent只要能匹配其中一组IntentFilter,即可成功启动对应的Activity.
匹配规则
action的匹配规则:
action的匹配规则要求Intent中的action存在且并必须和过滤规则中的其中一个action相同.
例如我们想要隐式启动过滤规则如下的Activity:
<activity android:name=".FilterActionActivity">
<intent-filter>
<action android:name="me.jesse.www.action1"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
<intent-filter>
<action android:name="me.jesse.www.action2"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
需要这样构建Intent:
Intent intent = new Intent();
intent.setAction("me.jesse.www.action1");
// intent.setAction("me.jesse.www.action2"); 或者这样
startActivity(intent);
category的匹配规则:
category的匹配规则要求Intent要么没有category.如果有category,每一个category都要和过滤规则中的category相同.
例:要启动过滤规则为这样的activity
<activity android:name=".FilterActionActivity">
<intent-filter>
<action android:name="me.jesse.www.action1"></action>
<category android:name="me.jesse.www.category1"></category>
<category android:name="me.jesse.www.category2"></category>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
<intent-filter>
<action android:name="me.jesse.www.action2"></action>
<category android:name="me.jesse.www.category3"></category>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
需要这样构建Intent:
//匹配第一组过滤规则:
Intent intent = new Intent();
intent.setAction("me.jesse.www.action1");
intent.addCategory("me.jesse.www.category1");
intent.addCategory("me.jesse.www.category2");
startActivity(intent);
//或者
Intent intent = new Intent();
intent.setAction("me.jesse.www.action1");
intent.addCategory("me.jesse.www.category1");
//intent.addCategory("me.jesse.www.category2");
startActivity(intent);
//或者
Intent intent = new Intent();
intent.setAction("me.jesse.www.action1");
//intent.addCategory("me.jesse.www.category1");
intent.addCategory("me.jesse.www.category2");
startActivity(intent);
//匹配第二组过滤规则:
Intent intent = new Intent();
intent.setAction("me.jesse.www.action2");
intent.addCategory("me.jesse.www.category3");
startActivity(intent);
//不匹配category
Intent intent = new Intent();
intent.setAction("me.jesse.www.action2");
startActivity(intent);
为什么不设置category也能匹配?
因为系统在调用startActivity()或startActivityForResult时会默认为intent加上"android.intent.category.DEFAULT"这个category.因此,如果一个activity设置了intentFilter,就必须为其手动加上<category android:name="android.intent.category.DEFAULT"></category>.否则该activity将无法通过隐式启动.
data的匹配规则
data的匹配规则与action类似:如果过滤规则定义了data,则intent中必须也要定义可匹配的data.
data的语法规则如下:
<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPrefix="string"
android:pathPattern="string"
android:mimeType="string"></data>
解析:
data由两部分组成:mimeType和URI.mimeType指媒体类型,如image/jpeg, audio/mpeg4-generic和video/*等.可以表示图片,文本,视频等不同的媒体格式.
URI的结构如下:
<scheme>: //<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
每个参数的含义:
scheme表示URI模式,如http, file, content等,不可省略.
host表示主机名,如www.baidu.com.
port表示端口号,如80,可以省略.
path,pathPattern,pathPrefix这三个参数表示路径信息.
例:要启动如下过滤规则的activity:
<intent-filter>
<action android:name="me.jesse.www.action2"></action>
<action android:name="me.jesse.www.action3"></action>
<category android:name="me.jesse.www.category3"></category>
<category android:name="android.intent.category.DEFAULT"></category>
<data android:mimeType="text/plain"></data>
</intent-filter>
可以这样构建Intent:
Intent intent = new Intent();
intent.setAction("me.jesse.www.action2");
intent.addCategory("me.jesse.www.category3");
intent.setDataAndType(Uri.parse("file://string"), "text/plain");
startActivity(intent);
疑问:为什么过滤规则中没有指定URI信息的情况下,intent的data传入的是file类型,而可以匹配成功呢?
因为过滤规则虽然没有明确指定URI,但却有默认值,默认值为content和file.