一、Intent与组件的关系
我们知道安卓有四大组件,其中的三种,Activity,Service,BroadCast都可以通过Intent进行数据传递。
(1)启动Activity,通过Intent传入startActivity方法来启动一个Activity的实例,同时,Intent也可以携带数据,传递给新的Activity。
(2)通过 Context.startService() 启动一个服务,或者通过Context.bindService() 和后台服务交互;
(3)通过广播方法(比如 Context.sendBroadcast(),Context.sendOrderedBroadcast(),
Context.sendStickyBroadcast()) 发给broadcast receivers。
我们都知道,启动Activity有两种方式,显示启动和隐式启动;隐式启动需要Intent能够匹配目标及组件的IntentFilter设置的过滤条件,如果不匹配,则无法启动对应的Activity。IntentFilter主要有三部分组成,action、category、data,下面是一个过滤条件的示例:
<activity android:name=".view.SecondActivity">
<intent-filter>
<action android:name="com.kevenzheng.view.c"/>
<action android:name="com.kevenzheng.view.d"/>
<category android:name="com.kevenzheng.category.c"/>
<category android:name="com.kevenzheng.category.d"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
为了匹配过滤规则,必须同时匹配action类别、category类别、data类别才算完全匹配,只有完全匹配,才能成功启动目标Activity。一个Activity可以有多个IntentFilter,一个Intent只要能够匹配一组IntentFilter即可启动对应的Activity。
1.action的匹配规则
action是一个字符串,系统预定义了一些action,我们也可以在应用中自定义自己的action。action的匹配规则是intent中的action必须和过滤规则中的action相同,也就是action的字符串值完全相同。一个过滤条件中可以有多个action,但是只需要与其中一个进行匹配则可。另外,action中的字符串区分大小写,大小写不同,则无法匹配成功。
2.category的匹配规则
category是一个字符串,系统预定义了一些category,但是我们也可以在自己的应用中自定义自己的category。category的匹配规则和action不同,它要求如果Intent中包含category,那么所有的category都必须和过滤规则中的其中一个category相同。如果Intent中没有category也是可以匹配成功的,因为系统在调用startActivity或者startActivityForResult的时候,会默认为Intent加入到“android.intent.category.DEFAULT”这个category,同时,我们为了Activity能够接受隐式启动,就必须在intentFilter中指定“android.intent.category.DEFAULT”这个category。
3、data的匹配规则
data的匹配规则和action类似,如果过滤规则中定义了data,那么Intent中也必须定义可匹配的data。
data的语法如下所示:
<data
android:host="string"
android:scheme="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string"
/>
data有两部分组成,一部分是mimeType,另一部分是URI。mimeType是媒体类型,比如image/jpeg、audio/mpeg4-generic和video/等,表示图片,文本,视频等不同的格式。而URI包含的数据就多了,<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>],举个百度的例子:
http://www.baidu.com:8080/search/info
Scheme:URI的模式,比如http、file、content等,如果URI中没有指定Scheme,那么这个URI是无效的。
Host:URI的主机名,比如www.baidu.com,如果host未定义,那么这个URI也是无效的。
Port:URI中的端口号,比如8080,仅当URI同时拥有scheme/host的时候,port才有意义。
Path、pathPattern、pathPrefix:这三个参数表示的是路径信息,path表示完整的路径信息;pathPattern也表示完整的路径信息,不过它里面可以包含通配符" * "," * "代表0个或多个任意字符,需要注意的是,由于正则表达式的规范,如果想表达真实的字符串,那么 " * "要写成" \ "," \ "要写成" \\ ";pathPrefix表示路径的前缀信息。
intent.setDataAndType(Uri.parse("file://abc"),"text/plain");
另外,如果要为Intent指定完整的data,必须要调用setDataAndType方法,因为单独调用setData或者setType,会彼此清除对方的值,这个可以通过查看源码获得。
当我们通过隐式方式启动一个Activity的时候,可以做下判断,查看是否有Activity能够匹配我们的隐式Intent,否则如果不存在此Activity,则会报错。判断的方法有两种:采用PackageManager的resolveActivity方法或者Intent的resolveActivity方法,如果找不到对应的Activity,则会返回null,我们通过判断,则会避免类似的错误。