IntentFilter的匹配规则

来源:互联网 发布:windows释放内存命令 编辑:程序博客网 时间:2024/05/06 20:30

启动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组件的匹配信息



0 0
原创粉丝点击