4.2.2 匹配组件的选择
如果有多个Intent Filter对象与调用组件发出的Intent对象都相匹配,就需要在所有符合条件的Intent Filter对象中进行筛选,选出最符合调用组件和用户需求的实现组件,这个流程就称做匹配组件的选择。
在组件选择上,最核心的机制就是基于优先级的排序。每个Intent Filter对象都有一个优先级,其范围从-1000(用常量IntentFilter.SYSTEM_LOW_PRIORITY表示)至1000(用常量IntentFilter.SYSTEM_HIGH_PRIORITY表示),值越大,表示该Intent Filter的优先级越高。默认情况下,Intent Filter对象的优先级为0,可通过<intent-filter>配置项中的android:priority属性进行变更,或者通过IntentFilter.setPriority函数进行动态地修改。
所有与调用组件Intent对象相匹配的Intent Filter对象,都会依照优先级从高至低进行排序。根据对组件的不同请求,使用不同的方式选择合适的实现组件。
来看一个实际利用Intent Filter优先级的例子。在Android中,包括原生的短信应用在内,都会通过添加Action为android.provider.Telephony.SMS_RECEIVED的Intent Filter接收短信消息:
<receiver android:name=".transaction.PrivilegedSmsReceiver">
<intent-filter>
<action
android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
而大量的第三方短信相关软件,都期望能够在其他短信应用接到短信通知之前提前拦截短信,做相应的处理。于是,开发者会采取提升Intent Filter优先级的策略来实现:
<receiver android:name="third_party.SmsReceiver">
<intent-filter>
<action android:priority="1000"
android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
而在third_party.SmsReceiver这个触发器组件中,系统可以定制策略拦截特定的短信,通过调用abortBroadcast()函数终止广播,使其他短信应用的Intent Filter无法匹配短信通知:
//根据短信内容终止广播,拦截短信
public void onReceive(Context context, Intent intent){
if(IsBlockedSms(intent)){
abortBroadcast();
}
}
小贴士 在组件进行意图匹配算法时,会计算出一个匹配度。但就目前而言,这个匹配度仅是作为错误码来使用的,匹配度的大小并未作为组件选择的依据。简而言之,匹配度的高低不会影响组件的选择,匹配度较低的组件,只要其优先级够高,依然会被优先选择。
而如果不同的Intent Filter对象优先级完全一致,Android则会根据组件名字的字母排序依次调用。