隐式Intent和<intent-filter>的匹配规则

来源:互联网 发布:淘宝全匿名回答提问 编辑:程序博客网 时间:2024/06/18 08:15

Intent可以划分成显式意图和隐式意图。

  • 显式意图:调用Intent.setComponent()或Intent.setClass()方法明确指定了Intent应该传递给哪个组件。这时候IntentFilter的对这种Intent没有约束力。
  • 隐式意图:没有明确指定组件名的Intent为隐式意图。 Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。这种情况下通过intent中的action,category,data,tpye 和Activity、Service、Broadcast Receiver中的IntentFilter进行匹配。若有多个目标组件同时可以匹配,则系统会提示用户进行选择。

隐式Intent和<intent-filter>的匹配规则

  1.  <intent-filter> 只包含action 和 category 只需要intent中的action 和 category 小于或等于<Intent-filter>范围,即可匹配成功(但是Intent必须指定action,否则系统报错)。
           例如:在AndroidManifest.xml 的定义如下
        <activity            android:name=".ui.AboutUsActivity">            <intent-filter>                <action android:name="testAction1" />                <action android:name="testAction2" />                <category android:name="android.intent.category.DEFAULT" />                <category android:name="category1" />                <category android:name="category2" />            </intent-filter>        </activity>

      注意: Activity 如果想被隐式Intent 启动则<intent-filter>必须包含 <category android:name="android.intent.category.DEFAULT" />,因为startActivity(intent) 时候,默认给intent添加了android.intent.category.DEFAULT 的category 属性值。Service和BroadcastReceiver不必要。

     下面是几个Intent

                intent1.setAction("testAction1");                Intent intent2 = new Intent();                intent2.setAction("testAction2");                Intent intent3 = new Intent();                intent3.setAction("testAction2");                intent3.addCategory("category1");                Intent intent4 = new Intent();                intent4.setAction("testAction1");                intent4.addCategory("category1");                intent4.addCategory("category2");                Intent intent5= new Intent();                intent5.setAction("testAction1");                intent5.addCategory("category1");                intent5.addCategory("category2");                intent5.addCategory("category3");                Intent intent6= new Intent();                intent6.addCategory("category1");
  上面intent1,intent2,intent3,intent4都可以正常启动activity。intent5因为范围超过了intent filter不能启动activity,intent6因为没有设置action不能启动activity。

2. <intent-filter> 除了action和categroy外还包含 type,则要求intent中的type和Intent-Filter中的type 完全一直才能匹配(Data 和 type 都是在<data></data>标签中定义的)。
 例如:在AndroidManifest.xml 的定义如下
 
   <activity android:name=".ui.AboutUsActivity">            <intent-filter>                <action android:name="testAction1" />                <data android:mimeType="abc/xyz" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </activity>
 下面是几个Intent:
                Intent intent1 = new Intent();                intent1.setAction("testAction1");                intent1.setType("abc/xyz");                Intent intent2 = new Intent();                intent2.setAction("testAction1");                Intent intent3 = new Intent();                intent3.setAction("testAction1");                intent3.setType("xxx/yyy");

 intent1可以正常启动,intent2因为没有设置type不能正常启动,intent3因为设置的type和intent filter 中的type 不一致不能启动activity。

3. <intent-filter> 除了action和categroy外还包含 Data,则要求intent中的scheme,host,prot,path和Intent-Filter存在的对应属性一致就可匹配。(Intent-Filter中定义的Data可以少于Intent中的Data属性)
  也就是Intent中的Data属性一定要包含Intent-Filter中的所有Data属性并且属性值要相等。Intent-Filter定义了Data,则要求Intent必须要包含Data,否则匹配失败。
 例如:在AndroidManifest.xml 的定义如下
 
    <activity android:name=".ui.AboutUsActivity">            <intent-filter>                <action android:name="testAction1" />                <action android:name="testAction2" />                <data                    android:host="www.csdn.com"                    android:mimeType="abc/xyz"                    android:scheme="lee" />                <category android:name="android.intent.category.DEFAULT" />                <category android:name="category1" />                <category android:name="category2" />            </intent-filter>        </activity>
  下面是几个Intent:
 <span style="white-space:pre"></span>Intent intent1 = new Intent();        intent1.setAction("testAction1");        intent1.setDataAndType(new Uri.Builder()                .scheme("lee")                .authority("www.csdn.com").build(), "abc/xyz");        Intent intent2 = new Intent();        intent2.setAction("testAction1");        intent2.setDataAndType(new Uri.Builder()                .scheme("lee")                .authority("www.csdn.com")                .path("/path").build(), "abc/xyz");        Intent intent3 = new Intent();        intent3.setAction("testAction1");        intent3.setDataAndType(new Uri.Builder()                .scheme("xxx")                .authority("www.csdn.com").build(), "abc/xyz");        Intent intent4 = new Intent();        intent4.setAction("testAction1");        intent4.setDataAndType(new Uri.Builder()                .scheme("lee").build(), "abc/xyz");


 intent1和intent-Filter 完全匹配  可以正常启动activity
intent2 中的Data属性比intent-filtet 属性多,可以正常启动activity
intent3 中的的Data属性值和intent-filter 的属性值不相等 不能启动activity
intent4 中的属性比intent-filter的属性值少  不能启动activity

1.如果Intent Filter中同时定义了data和Type,需要调用setDataAndType方法,不能调用setData 和 setType,两个方法相互覆盖
2.如果Intent Filter中要设置path,path的值的前面要加上"/"(在实际使用发发现没有"/",无法正常触发)。例如设置android:path="/main" 则intent.setData(new Uri.Builder().path("main").build) 和设置intent.setData(new Uri.Builder().path("/main").build()) 都可以。
 

0 0
原创粉丝点击