开发艺术探索阅读-IntnetFilter的匹配规则
2016-04-24 00:43
260 查看
1.3 IntentFilter的匹配规则
启动activity分为两种:1. 显示调用
2. 隐式调用
隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息,如果不匹配将无法启动目标activity
IntentFilter中的过滤信息有action、category、data
<activity android:name = "xxx.xxx.xxx" android:label = "xxx" android:launchMode = "singleTask" android:taskAffinity = "com.xxx.task1"> <intent-filter> <action android:name = "com.xxx.charpter_1.c"/> <action android:name = "com.xxx.charpter_1.d"/> <category android:name = "con.xxx.category.c"/> <data android:mimeType = "text/plain" </intent-filter> </activity>
注意:
为了匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失败。一个过滤列表的action、category、data可以有多个,所有的action、category、data分别构成不同类别,同一个类别的信息共同约束当前类型的匹配过程。只有一个Intent**同时匹配**action,category,data类别才算完全匹配一个activity可以有多个Intent-filter,一个intent只需要匹配上其中一组就可以启动对应的activity
各项属性的匹配规则
1.action的匹配规则
action是一个字符串,系统预先定义了一些action,同时我们也可以在应用中定义自己的actionIntent中的action能够和过滤规则中的任何一个action相同即可匹配成功
Intent中如果没有指定action,那么匹配失败,action的匹配要求Intent中的action必须存在
action区分大小写,大小写不同字符串相同的action会匹配失败
2.category的匹配规则
category是一个字符串,系统预定义了一些category,同时我们也可以在应用中定义自己的category与action匹配规则不同的是,如果在Intent中定义了多个category,那么每一个都必须和IntentFilter中的category中的一个相同,如果Intent中没有category,按照上面的描述,这个Intent仍然可以匹配成功
为什么不设置category系统也可以匹配上呢?
系统调用startActivity的时候或者startActivityResult的时候会默认为Intent加上”android.intent,DEFAULT”这个category,同时,为了我们的activity能够接受隐式调用,必须在intent-filter中指定”android.intent.category.DEFAULT”
3.data的匹配规则
data的匹配规则和action类似,如果定义了data,那么Intent必须也要定义可匹配的data,在介绍data的匹配规则之前,我们需要先了解一下data的结构,因为data稍微有点复杂.<data android:scheme = "string" android:host = "string" android:port = "string" android:path = "string" android:pathPattern = "string" android:pathPrefix = "string"/>
data由两部分组成,mimeType和URI。mimeType 指媒体类型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等不同的媒体格式、而URI中包含的数据就比较多了
<scheme>://<host>:<port>/<[<path>|<pathPrefix>|<pathPattern>]
这里在给几个实际的例子就比较好理解了
content://com.example.project:200/folder/subfolder/etc http://www.baidu.com:80/search/info
Scheme : URI的模式,比如file、http、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效,这也意味着URI是无效的
Host : URI的主机名,比如www.baidu.com,如果host未指定,那么整个URI中的其他参数都无效,这也意味着URI是无效的
Port : URI的端口号,比如80,仅当URI中指定了scheme和host参数的时候,port参数才有意义
path、pathPattern、pathPrefix : 这三个参数表述路径信息:
1. path表示完整的路径
2. pathPattern也表示完整的路径信息名单是它里面可以包含通配符” * “,*表示0个或者多个任意字符,需要注意的是由于正则表达式,想表达出真是的字符串,
那么"*"要写成\\* "\"要写成"\\\\"
3. pathPrefix表示路径的前缀信息
<1>这种过滤规则
<intent-filter> <data android:mieType = "image/*"/> </intent-filter>
这种过滤规则制定了媒体类型为所有类型的图片,那么Intent中的mimeType属性必须为”image/*”才能匹配
这种情况下虽然没有指定URI,但是却有默认值,默认值为contnet和file
也就是说,虽然没有指定URI,但是Intent的URI部分的scheme必须为content或者file才能匹配
为了匹配<1>中的必须写成
intent.setDataAndType(Uri.parse("file//abc),"image/png]")
另外,如果要为Intent指定完成的data,必须要调用setDataAndType方法,不能先调用setData再调用setType方法,因为这两个方法会清除对方的值,这个看源码就很容易会理解
setData会把mimeType置为null,同理setType也会把URI置为null
<2>如下过滤规则
<intent-filter> <data android:mimeType = "video/mpeg" android:scheme = "http".../> <data android:mimeType = "audio/mpeg" android:scheme = "http".../> </intent-filter>
我们可以写出如下示例
intent.setDataAndType(Uri.parse("http://abc"),"video/mpeg")
或者
intent.setDataAndType(Uri.parse("http://abc"),"audio/mpeg")
data的两种写法,作用一样,
<Intent-filter...><data android:scheme = "file" android:host = "www.baidu.com"/> </Intent-filter> <intent-filter...> <data android:scheme = "file"/> <data android:host = "www.baicu.com"/> </intent-filter...>
现在我们给出完全匹配它的Intent
Intent intent = new Intent("com.ryg.charpter_1.c"); intent.addCategory("com.ryg.category.c"); intent.setDataAndType(Uri.parse("file://abc"),"text/plain"); startActivity(intent);
Intent-filter的匹配规则对于Service和BroadcastReceiver也是同样的道理,不过系统对于service的建议是尽量使用显式调用方式来启动服务
我们通过隐式调用启动一个activity的时候,可以先做一下判断,看是否有activity匹配我们的activity,一般方法有两种
1. 采用packagemanager的resolveActivity方法或者Intent的resolveActivity方法,如果他们找不到匹配的activity就会返回null,我们通过判断返回值就可以规避错误
2. packageManager还提供了queryIntentActivities方法,这个方法和resolveActivity方法不同的是:它不是返回最佳匹配的activity信息而是返回所有成功匹配的activcity信息
public abstract List<ResolveInfo> queryIntentActivitied(Intent intent,int flags) public abstract ResolveInfo resolveActivity(Intent intent,int flags);
上述两个方法的第一个参数比较好理解,第二个参数需要注意,我们需使MATCH_DEFAULT_ONLY这个标记位,这个标记位的含义是仅仅匹配那些在intent-filter中声明这个category的Activity,意义在于[b]只要返回值不为null,那么startActivity一定可以成功 ;[/b]
如果不用,就可以把intent-filter中category不含DEFAULT的那些activity匹配出来,从而导致startactivity可能失败。因此,不含有DEFAULT这个category的activity是无法接受隐式Intent,在action和category中,有一类action和category是比较重要的他们是
<action android:name = "android.intent.action.MAIN"/> <action android:name = "android.intent.category.LAUNCHER"/>
这两者共同作用是表明这是一个入口activity,并且会出现在系统的应用列表中,少了任何一个都没有实际意义,也无法出现在系统的应用列表
针对Service和BroadCastReceiver,packageManager同样提供了类似的方法去获取成功匹配的组件信息
相关文章推荐
- log4j的优先级解读与简单实例
- 求S=a+aa+aaa+aaaa+aa...a的值
- 找出数组中只出现一次的2个数字
- Fragment的Tab加载方式
- 求S=a+aa+aaa+aaaa+aa...a的值
- IL指令初识和.NET Reflector&&ILDASM,ILASM使用
- 开发艺术探索总结-activity的启动模式
- bzoj4516 [Sdoi2016]生成魔咒
- 第 4 章 表单和图片
- Makefile 使用总结
- 书面格式解惑篇
- 静态链接库和动态库的引入库lib文件的区别
- 个人工作总结6
- linux 查看删除进程 ps命令详解
- uboot异常向量表---嵌入式回归第六篇
- Java语言的非对称加密的实现
- 程序源入坑之路4(web)
- 开发艺术探索阅读总结(1.2)异常情况下的生命周期分析
- 内存错误几点
- 经典全屏滚动插件fullPage.js