IntentFilter匹配规则

本文详细解析了Android中IntentFilter的匹配规则,包括action、category和data的匹配条件。理解这些规则对正确使用隐式启动至关重要。文章还提供了一个完整的匹配示例,并讨论了特殊IntentFilter的应用场景,最后给出了最佳实践,强调在隐式启动前应先检查匹配可行性,以提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

我们都知道,启动Activity有两种方式,即隐式启动显式启动。从优先级来说,显式启动要优先于隐式启动。隐式启动的优点是使用上的灵活性。因此,掌握隐式启动中IntentFilter的匹配规则就至关重要了。

对一个Activity而言,可以在AndroidManifest文件中指定多个IntentFilter,Intent只要能够匹配其中任意一个就算匹配成功。在一个IntentFilter中,可以有多个action、category和data。所有的action组成action类别。同理,所有的category和data分别组成category类别和data类别。Intent需要和action类别、category类别和data类别全部匹配成功,才算是和这个IntentFilter匹配成功。针对不同的类别,有着不同的匹配规则,具体细节见下文。

action的匹配规则

直观来说,action是一个字符串。Android系统提供了一些预定义的action,它们都有着自己的含义,我们可以直接使用。当然,我们也可以定义自己的action,以便满足我们自己的业务需求。在一个IntentFilter中,可以有多个action。Intent只要能和其中任意一个 action匹配就算是匹配成功。否则,匹配失败。

category的匹配规则

category也是一个字符串,Android系统同样为我们提供了一些预定义的category。当然,我们也可以定义自己的category。category的匹配规则和action有所不同。一个IntentFilter中可以有多个category,并不要求Intent全部匹配。但是,要求Intent中添加的任意一个category,都必须已经包含在IntentFilter中了,否则匹配失败。

需要注意的是,即使不为Intent添加category,在调用startActivity或者startActivityForResult方法后,Android系统都会为Intent添加一个预定义的category,即android.intent.category.DEFAULT。因此,我们需要为Activity的IntentFilter指定这个category,否则会造成匹配失败。

data的匹配规则

相比action和category,data的匹配规则要稍微复杂一点。首先,要明白data分为URImimeType两部分。一个典型的data结构如下所示:

<data
    android:scheme="string"
    android:host="string"
    android:port="string"
    android:path="string"
    android:pathPattern="string"
    android:pathPrefix="string"
    android:mimeType="string">
 </data>

android:mimeType属性指定了mimeType部分,主要是指定媒体类型。如text/plain、video/*等。URI部分则由剩余的属性共同组成。一个URI的结构如下:

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

具体的属性含义如下:

  • scheme:URI的协议名,如http、file、content等,必须指定。
  • host:URI的主机名,如www.coding.com,必须指定。
  • port:URI的端口名,可选。
  • path、pathPrefix和pathPattern:共同组成URI的路径内容。path和pathPattern都表示完整路径。不同之处在于pathPattern可以指定通配符*。pathPrefix则表示路径前缀。

一个IntentFilter可以包含多个data,Intent只要能够匹配其中任何一个data就算是匹配成功。对于单个data而言,Intent需要匹配所有内容才算是匹配成功。

需要注意的是,如果一个data没有指定URI部分,而只是指定了mimeType部分,这个data也是有默认URI的。URI部分会被Android系统指定为file和content。例如一个data如下:

<data android:mimeType="text/plain"></data>

如果我们要匹配这个data,就需要在Intent中指定URI为file或者content才行。如下所示:

Intent intent=new Intent();
intent.setDataAndType(Uri.parse("file://"),"text/plain");

需要注意的是,应该使用setDataAndType方法为Intent设置URI和mimeType。因为如果单独使用setDatasetType,它们会相互清除对方设置的值。

一个完整的匹配示例

IntentFilter如下所示:

<intent-filter>
      <action android:name="com.codingending.action.test_1"></action>
      <action android:name="com.codingending.action.test_2"></action>

      <category android:name="com.codingending.category.test_1"></category>
      <category android:name="com.codingending.category.test_2"></category>
      <category android:name="android.intent.category.DEFAULT"></category>

      <data android:mimeType="text/plain"></data>
 </intent-filter>

如果想要匹配上述IntentFilter,可以采取下面的方式:

Intent intent=new Intent();
intent.setAction("com.codingending.action.test_1");
intent.addCategory("com.codingending.category.test_1");
intent.setDataAndType(Uri.parse("file://"),"text/plain");

或者:

Intent intent=new Intent();
intent.setAction("com.codingending.action.test_2");
intent.addCategory("com.codingending.category.test_1");
intent.addCategory("com.codingending.category.test_2");
intent.setDataAndType(Uri.parse("file://"),"text/plain");

特殊的IntentFilter

在Android存在一个特殊的IntentFilter,如下所示:

<intent-filter>
     <action android:name="android.intent.action.MAIN" />
     <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

这个IntentFilter的作用是标识其所在的Activity是应用的入口Activity,即主Activity。这是应用启动后呈现给用户的第一个Activity。

最佳实践

使用隐式启动方式最大的缺点是可能匹配失败造成应用出现ForceClose错误,这样会给用户不好的使用体验。因此,在使用隐式启动方式时,最好先查询一下是否存在能够匹配的Activity。只有存在能够匹配的Activity时,才真正地去启动它。要达到这一目的,可以使用Intent的resolveActivity方法。或者,也可以使用PackageManagerresolveActivityqueryIntentActivities方法。它们的方法原型如下所示:

Intent:

public ComponentName resolveActivity(PackageManager pm);

packageManager:

public abstract ResolveInfo resolveActivity(Intent intent, int flags);
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,int flags);

resolveActivityqueryIntentActivities的不同之处在于,前者会返回最佳的匹配结果,而后者将返回所有匹配成功的结果。

对于这两个方法中的flags参数,可以选择MATCH_DEFAULT_ONLY或者MATCH_ALL,一般选择前者。如果使用MATCH_DEFAULT_ONLY参数,匹配过程中将会忽略category中不含android.intent.category.DEFAULT的Activity,因为这些Activity无法被启动。原因前文已经说过。

通过判断这些方法的返回值是否为null,可以知道是否能够匹配成功。这样处理后,可以避免应用出现ForceClose错误,也优化了用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值