前言
好久没写APP了,关于Intent和<intent-filter>
的匹配规则,忘了很多,索性好好读了下官方稳定,总结(翻译)如下。
1. Action 解析规则
1.1 intent-filter 填写规则
-
每个
<intent-filter> </intent-filter>
对中,可以指定0个到N个<action>
元素 -
例如:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
1.2 解析规则
- 如果一个Intent中指定了action项
- 如果这个action至少匹配
<intent-filter> xxx </intent-filter>
中的一个action,则匹配通过,否则失败; - 如果
<intent-filter> xxx </intent-filter>
中没有任何action项,则直接匹配失败
- 如果这个action至少匹配
- 如果一个Intent中没有指定任何action项
- 如果
<intent-filter> xxx </intent-filter>
中至少一个action,则匹配通过
- 如果
1.3 特殊说明
如果使用的是隐式Intent,安卓会自动在调用startActivity()和startActivityForResult()
接口的时候,自动在intent对象中添加<category android:name="android.intent.category.DEFAULT" />
声明。所以,在这种情况下,如果你想让你的activity接收这些intent对象,就必须在其<intent-filter> </intent-filter>
中添加<category android:name="android.intent.category.DEFAULT" />
。
-
例如
<activity android:name=".test.ex01_intent.test_ex01_activity1" android:label="@string/title_activity_test_ex01_activity1"> <intent-filter> <action android:name="myaction.test.ex01.activity1" />/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
-
调用代码如下:
mBtn01.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent("myaction.test.ex01.activity1"); startActivity(intent); } });
2. Category 解析规则
2.1 intent-filter 填写规则
-
每个
<intent-filter> </intent-filter>
对中,可以指定0个到N个<category>
元素 -
例如:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
2.2 解析规则
- 如果一个Intent中指定了1到N个category项
- 则这个intent对象中的1到N个category,在
<intent-filter> xxx </intent-filter>
中,需要全有,一一匹配则通过,否则失败;- 注意:
<intent-filter>
中的项目可以比intent对象中的category多,只要intent中的全都匹配到,就可以通过
- 注意:
- 则这个intent对象中的1到N个category,在
- 如果一个Intent中没有指定任何category项
- 则,无论
<intent-filter> xxx </intent-filter>
中有多少个category,直接匹配通过
- 则,无论
2.3 特殊说明
- 如果使用的是隐式Intent,安卓会自动在调用startActivity()和
startActivityForResult()
接口的时候,自动在intent对象中添加<category android:name="android.intent.category.DEFAULT" />
声明。所以,在这种情况下,如果你想让你的activity接收这些intent对象,就必须在其<intent-filter> </intent-filter>
中添加<category android:name="android.intent.category.DEFAULT" />
,具体可参考楼上action 1.3节。
3. Data 项解析规则
3.1 intent-filter 填写规则
-
每个
<intent-filter> </intent-filter>
对中,可以指定0个到N个<data>
元素 -
例如:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
-
每个
<data>
项目都可以指定一个URI和一个数据类型。 -
每个URI都可包含
scheme
,host
,port
,path
这几属性,其格式为<scheme>://<host>:<port>/<path>
-
举例:
content://com.example.project:200/folder/subfolder/etc
<scheme>
为 content<host>
为com.example.project<port>
为200<path>
为 folder/subfolder/etc
-
注意:每个
<data>
项目中的URI,scheme
,host
,port
,path
这几个属性,不是全都需要指定,但有一个线性的依赖要求:- 如果
<scheme>
没有被指定,则后面的<host>
被忽略。 - 如果
<host>
没有被指定,则后面的<port>
被忽略。 - 如果
<scheme>
和<host>
都没有被指定,则后面的<path>
被忽略。
- 如果
3.2 data 匹配规则
-
当Intent中的URI与
<intent-filter>
中的一个URI相对比的时候:- 如果
<intent-filter>
中的这个URI只有一个<scheme>
,则Intent对象中拥有相同<scheme>
的URI,全部通过。 - 如果
<intent-filter>
中的这个URI指定了<scheme>
和<authority>
,但是没有指定<path>
,则Intent对象中拥有相同<scheme>
和<authority>
的URI,不管其<path>
是什么值,全部通过。 - 如果
<intent-filter>
中的这个URI指定了<scheme>
、<authority>
和<path>
,则Intent对象中拥有相同<scheme>
、<authority>
和<path>
的URI,才能通过。 - 注意:
<path>
中可以使用*
通配符
- 如果
-
数据测试会将 Intent 中的 URI 和 MIME 类型与
<intent-filter>
中指定的 URI 和 MIME 类型进行比较。规则如下:-
仅当
<intent-filter>
未指定任何 URI 或 MIME 类型时,不含 URI 和 MIME 类型的 Intent 才会通过测试。 -
对于包含 URI 但不含 MIME 类型(既未显式声明,也无法通过 URI 推断得出)的 Intent,仅当其 URI 与
<intent-filter>
的 URI 格式匹配、且<intent-filter>
同样未指定 MIME 类型时,才会通过测试。 -
仅当
<intent-filter>
列出相同的 MIME 类型且未指定 URI 格式时,包含 MIME 类型但不含 URI 的 Intent 才会通过测试。 -
仅当 MIME 类型与
<intent-filter>
中列出的类型匹配时,同时包含 URI 类型和 MIME 类型(通过显式声明,或可以通过 URI 推断得出)的 Intent 才会通过测试的 MIME 类型部分。如果 Intent 的 URI 与<intent-filter>
中的 URI 匹配,或者如果 Intent 具有content:
或file:
URI 且<intent-filter>
未指定 URI,则 Intent 会通过测试的 URI 部分。换言之,如果过滤器只是列出 MIME 类型,则假定组件支持content:
和file:
数据。 -
**注意:**如果 Intent 指定 URI 或 MIME 类型,则数据测试会在
<intent-filter>
中没有<data>
元素时失败。
-
4. 例子:intent-filter 同时包含 action、category、data
AndroidManifest
- 如下AndroidManifest ,在1.3的基础上,添加了
<data>
<activity
android:name=".test.ex01_intent.test_ex01_activity1"
android:label="@string/title_activity_test_ex01_activity1">
<intent-filter>
<!-- <action android:name="android.intent.action.MAIN" />-->
<action android:name="myaction.test.ex01.activity1" />/>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/mpeg" android:scheme="http" />
</intent-filter>
</activity>
(1)测试代码:启动activity 失败
mBtn01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("myaction.test.ex01.activity1");
startActivity(intent);
}
});
(2)测试代码:启动activity 失败
mBtn01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mMyAction);
intent.setType("video/mpeg");
startActivity(intent);
}
});
(3)测试代码:启动activity 失败
mBtn01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mMyAction);
intent.setType("video/mpeg");
intent.setData(Uri.parse("http"));
startActivity(intent);
}
});
原因如下:
- intent.setData(Uri.parse(“http”));语句中scheme部分未识别到
- 若要识别,需改为intent.setData(Uri.parse(“http://”));
(4)测试代码:启动activity 成功
mBtn01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mMyAction);
intent.setType("video/mpeg");
intent.setData(Uri.parse("http://"));
startActivity(intent);
}
});
总结
从下面几个实验可以看到,当同时包含这三项,则需要三项同时依据各自匹配规则,三项均通过才行