IntentFilter的匹配规则

本文详细介绍了Android中IntentFilter的工作原理及匹配规则,包括action、category和data三方面的具体匹配流程,并给出了启动Activity前进行匹配判断的方法。

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

启动Activity分为两种,显式调用和隐式调用。显式调用需要明确地指定被启动对象的组件信息,比如包名和类名;隐式调用不需要明确指定组件信息,需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息。


IntentFilter中的过滤信息有action、category、data。一个过滤列表中可以有多个action、category和data可以有多个。一个Intent同时匹配action类别、category类别、data类别才算完全匹配。一个Activity中可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应的Activity。


1、action的匹配规则

action是一个字符串,系统预定了一些action,我们也可以在应用中定义自己的action。这里的匹配指的是action的字符串值完全相同。一个过滤规则中可以有多个action,那么Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功。如果Intent中没有指定action,那么匹配失败。另外,action区分大小写。


2、category的匹配规则

category是一个字符串,系统预定了一些category,我们也可以在应用中定义自己的category。Intent可以没有category,如果Intent包含了category,则必须每一个category都能与过滤规则中的category匹配。系统调用startActivity或startActivityResult的时候会默认为Intent加上"android.intent.category.DEFAULT",所以Intent可以没有category。同时,为了我们的Activity能接收隐式调用,就必须在intent-filter中指定"android.intent.category.DEFAULT"。


3、data的匹配规则

data语法如下:

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

data由mimeType与URI组成,mimeType指媒体类型,比如image/jpeg等;URI的结构如下:

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

实际例子:http://www.baidu.com:80/search/info

scheme:默认值为content或file

path:表示完整路径

pathPattern:包含通配符的完整路径;通配符“*”表示0个或多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么“*”要写成“\\*”,“\”要写成“\\\\”

pathPrefix:表示路径的前缀信息

Intent中的data数据能够完全匹配过滤规则中的某一个data,则匹配成功
Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法会清楚对方的值:

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

最后,当我们用隐式启动一个Activity的时候,应该先做一下判断,不然匹配失败,就会抛出异常。

判断方法:

1、PackageManager的resolveActivity方法:找不到匹配的Activity,就会返回null

Intent intent = new Intent(Intent.ACTION_VIEW);  
intent.setDataAndType(Uri.parse(url), mimetype);  
if (getPackageManager().resolveActivity(intent,  PackageManager.MATCH_DEFAULT_ONLY) != null) {    
       try {  
                  startActivity(intent);  
                  return;  
             } catch (ActivityNotFoundException ex) {  
                    if (Config.LOGD) {  
                        Log.d(LOGTAG, "activity not found for " + mimetype  
                                + " over " + Uri.parse(url).getScheme(), ex);  
             }  
                      
}  

2、Intent的resolveActivity方法:找不到匹配的Activity,就会返回null

Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-2368"));  

PackageManager pm = context.getPackageManager();  
ComponentName cn = intent.resolveActivity(pm);  
if (cn == null) {  
    Uri marketUri = Uri.parse("market://search?q=pname:com.myapp.packagename");  
    Intent marketIntent = new Intent(Intent.ACTION_VIEW).setData(marketUri);  
    if (marketIntent.resolveActivity(pm) != null) {  
        context.startActivity(marketIntent);  
    } else {  
        Log.d(TAG, "Market client not available.");  
    }  
} else{  
    context.startActivity(intent);  
} 

3、PackageManager的queryIntentActivities方法:与上面两种方法不同的是,它不是返回最佳匹配的Activity信息而是返回所有成功匹配的Activity信息
PackageManager packageManager = context.getPackageManager();  
Intent intent = new Intent(action);  
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);  
if (resolveInfo.size() > 0) {  
    return true;  
}  
return false;

queryIntentActivities和resolveActivity的方法原型:


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


public abstract ResolveInfo resolveActivity (Intent intent, int flags) 


上述两个方法中第二个参数,我们要使用MATCH_DEFAULT_ONLY这个标记位,它的含义仅仅匹配那些在intent-filter中的声明了<category android:name="android.intent.category.DEEFAULT">的Activity。这样就可以避免匹配到不包含DEFAULT这个category的Activity。

intent-filter匹配规则对于Servce和BroadcastReceiver也是同样的道理,PackageManager也提供了类似的方法去获取Service和BroadcastReceivcer组件的匹配信息



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值