Intent
1、概述
一个应用程序的三个核心组件——activities、services、broadcast receivers,都是通过叫做intent的消息激活。
- Activity:一个intent对象传递给Context.startActivity()或Activity.startActivityForRestult()去启动一个活动或使一个已存在的活动去做新的事情。
- Service:一个intent对象传递给Context.startService()去初始化一个service或传递一个新的指令给正在运行的service。类似的,一个intent可以传递给Context.bindService()去建立调用组件和目标服务之间的连接。
- Broadcast Receiver:一个intent对象传递给任何广播方法(如Context.sendBroadcast(),Context.sendOrderedBroadcast(),Context.sendStickyBroadcast()),都将传递到所有感兴趣的广播接收者。
2、显示意图和隐式意图
- 显式intent:通过名字指定目标组件。因为开发者通常不知道其它应用程序的组件名字,显式intent通常用于应用程序内部消息,如一个活动启动从属的服务或启动一个姐妹活动。
- 隐式intent:并不指定目标的名字(组件名字字段是空的)。隐式intent经常用于激活其它应用程序中的组件。
3、Intent-filter
1)动作检测
清单文件中的元素以子元素列出动作,例如:
<intent-filter . . . >
<action android:name="com.example.project.SHOW_CURRENT" />
<action android:name="com.example.project.SHOW_RECENT" />
<action android:name="com.example.project.SHOW_PENDING" />
. . .
</intent-filter>
虽然一个Intent对象仅是单个动作,但是一个过滤器可以列出不止一个。这个列表不能够为空,一个过滤器必须至少包含一个子元素,否则它将阻塞所有的intents。
要通过检测,Intent对象中指定的动作必须匹配过滤器的动作列表中的一个。如果对象或过滤器没有指定一个动作,结果将如下:
- 如果过滤器没有指定动作,没有一个Intent将匹配,所有的intent将检测失败,即没有intent能够通过过滤器。
- 如果Intent对象没有指定动作,将自动通过检查(只要过滤器至少有一个过滤器,否则就是上面的情况了)
2)种类检测
类似的,清单文件中的元素以子元素列出种类,例如:
<intent-filter . . . >
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
. . .
</intent-filter>
对于一个intent要通过种类检测,intent对象中的每个种类必须匹配过滤器中的一个。即过滤器能够列出额外的种类,但是intent对象中的种类都必须能够在过滤器中找到,只要一个种类在过滤器列表中没有,就算种类检测失败!
因此,原则上如果一个intent对象中没有种类(即种类字段为空)应该总是通过种类测试,而不管过滤器中有什么种类。但是有个例外,Android对待所有传递给Context.startActivity()的隐式intent好像它们至少包含”android.intent.category.DEFAULT”(对应CATEGORY_DEFAULT常量)。因此,活动想要接收隐式intent必须要在intent过滤器中包含”android.intent.category.DEFAULT”。
注意:”android.intent.action.MAIN” 和 “android.intent.category.LAUNCHER”设置,它们分别标记活动开始新的任务和带到启动列表界面。它们可以包含”android.intent.category.DEFAULT”到种类列表,也可以不包含。
3)数据检测
类似的,清单文件中的元素以子元素列出数据,例如:
<intent-filter . . . >
<data android:mimeType="video/mpeg" android:scheme="http" . . . />
<data android:mimeType="audio/mpeg" android:scheme="http" . . . />
. . .
</intent-filter>
元素指定一个URI和数据类型(MIME类型)。它有四个属性scheme、host、port、path对应于URI的每个部分:
scheme://host:port/path
例如,下面的URI:
content://com.example.project:200/folder/subfolder/etc
scheme是content,host是”com.example.project”,port是200,path是”folder/subfolder/etc”。host和port一起构成URI的凭据(authority),如果host没有指定,port也被忽略。 这四个属性都是可选的,但它们之间并不都是完全独立的。要让authority有意义,scheme必须也要指定。要让path有意义,scheme和authority也都必须要指定。
当比较intent对象和过滤器的URI时,仅仅比较过滤器中出现的URI属性。例如,如果一个过滤器仅指定了scheme,所有有此scheme的URIs都匹配过滤器;如果一个过滤器指定了scheme和authority,但没有指定path,所有匹配scheme和authority的URIs都通过检测,而不管它们的path;如果四个属性都指定了,要都匹配才能算是匹配。然而,过滤器中的path可以包含通配符来要求匹配path中的一部分。
元素的type属性指定数据的MIME类型。Intent对象和过滤器都可以用”“通配符匹配子类型字段,例如”text/“,”audio/*”表示任何子类型。
数据检测既要检测URI,也要检测数据类型。规则如下:
一个Intent对象既不包含URI,也不包含数据类型:仅当过滤器也不指定任何URIs和数据类型时,才能通过检测
一个Intent对象包含URI,但不包含数据类型:仅当过滤器也不指定数据类型,同时它们的URI匹配,才能通过检测。例如,mailto:和tel:都不指定实际数据。
一个Intent对象包含数据类型,但不包含URI:仅当过滤也只包含数据类型且与Intent相同,才通过检测。
一个Intent对象既包含URI,也包含数据类型(或数据类型能够从URI推断出):数据类型部分,只有与过滤器中之一匹配才算通过;URI部分,它的URI要出现在过滤器中,或者它有content:或file:
URI,又或者过滤器没有指定URI。换句话说,如果它的过滤器仅列出了数据类型,组件假定支持content:和file: 。