AS 隐式Intent

本文详细解释了Android系统如何通过IntentAction、类别和数据测试来决定哪个Activity响应隐式Intent。涵盖了intent过滤器的声明与Intent匹配的详细规则,包括scheme、category和mimeType的使用示例。
摘要由CSDN通过智能技术生成

当系统收到隐式 Intent 以启动 Activity 时,它根据以下三个方面将该 Intent 与 Intent 过滤器进行比较,搜索该 Intent 的最佳 Activity:

  • Intent Action
  • Intent data(URI 和数据类型)
  • Intent category

下文根据如何在应用的清单文件中声明 Intent 过滤器,描述 Intent 如何与相应的组件匹配。

1. Action 测试

为指定可接受的intent 动作,可以在filter中定义0个以上的<action>元素,例如:

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

为通过这个filter,在Intent中指定的动作必须匹配这个表中的某一项。(包含关系)

如果filter中没有列出任何action,那么就没有动作能够用来与intent相匹配,所以,所有的intents都不能通过测试,没有intents可以通过过滤器。但是,如果Intent没有指定action,则通过filter(但是filter中至少得有一个action)。


2. 类别测试

要指定接受的 Intent 类别, Intent 过滤器既可以不声明任何 <category> 元素,也可以声明多个该类元素。 例如:

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>

若要使 Intent 通过类别测试,则 Intent 中的类别应是过滤器中的类别的子集因此,不含类别的 Intent 应当始终会通过此测试,无论过滤器中声明何种类别均是如此。

:Android 会自动将 CATEGORY_DEFAULT 类别应用于传递给 startActivity() 和 startActivityForResult() 的所有隐式 Intent。因此,如需 Activity 接收隐式 Intent,则必须将 "android.intent.category.DEFAULT" 的类别包括在其 Intent 过滤器中(如上文的 <intent-filter> 示例所示)。


3. 数据测试

要指定可接受的 Intent 数据, Intent 过滤器既可以不声明任何 <data> 元素,也可以声明多个此类元素。 例如:

<intent-filter>
    <data android:mimeType="video/mpeg" android:scheme="http" ... />
    <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    ...
</intent-filter>

每个 <data> 元素均可指定 URI 结构数据类型(MIME 媒体类型)URI 的每个部分均包含单独的 scheme、host、port 和 path 属性:

<scheme>://<host>:<port>/<path>
例如:
content://com.example.project:200/folder/subfolder/etc
在此 URI 中,方案(scheme)是 content,主机是 com.example.project,
端口是 200,路径是 folder/subfolder/etc。

<data>元素中,每个属性是可选的,但是也有相互依赖:

  • 如果没有指定scheme,host会被忽略
  • 如果没有指定host,则port会被忽略
  • 如果没有指定scheme和host,则path会被忽略

当intent中的URI和filter中的URI进行比对的时候,只比对filter中的URI部分,例如:

  • 如果filter中只有scheme,则所有的相同scheme均匹配该filter
  • 如果filter中指定了scheme和authority,但是没有path,则所有的具有相同scheme和authority的URI均通过该filter,而忽略掉它们的path
  • 如果filter指定了scheme、authority和path,则相同的scheme,authority和path才能通过filter。

注意:在path中可以包含通配符

在data测试的时候,在intent中的URIMIMEfilter中的进行比对,规则如下:

  1. 一个既不包含URI又没有指定数据类型的Intent对象只有在过滤器同样什么都没指定的情况下才能通过测试。
  2. 任意一个只包含了URI但没有数据类型(并且无法从URI中推断出其类型)只有在这个URI与过滤器中的一个URI相匹配,并且同样没有指定数据类型的情况下通过测试。当URI为mailto:和tel:时即为这种情况,并不能确切的知道数据类型。
  3. Intent对象中包含了一个数据类型但没有URI时,只有在过滤器列举了相同的数据类型,并且类似也没有指定URI时通过测试。
  4. Intent对象同时包含了一个URI和一个数据类型(如数据类型可以由URI推断出),类型部分只有在该类型与过滤器中所列类型匹配时才能通过测试。URI部分,要么URI与过滤器的中某个匹配,要么其包含了一个content:或file:URI并且过滤器没有指定一个URI。换句话说,如果过滤器中只指定了数据类型,那么一个组件默认的支持content:和file:数据。

最后一条规则反映了组件可以从文件或者content provider中获取本地数据。因此,filter中可以只有数据类型而不需要显式的命名content:和file: scheme,下例告诉android,组件可以从content provider中获取image数据并显示出来:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

因为大部分可用的数据是来自于content provider,只指定数据类型而没有URI的情况比较普遍。

另外一个比较普遍的配置为,filter中有一个scheme和一个数据类型。例如,下例,<data>元素告诉android,该组件从网络中获取视频数据。

<intent-filter>
    <data android:scheme="http" android:type="video/*" />
    ...
</intent-filter>

data 标签的属性含义

scheme, host, port, path, pathPrefix, pathPattern 是用来匹配 Intent 中的 Data Uri 的。具体规则如下:

scheme://host:port/path 或 pathPrefix 或 pathPattern

最后的 "path 或 pathPrefix 或 pathPattern" 是指后面的 path 验证可以使用 data 属性中的 android:path、android:pathPrefix 或 android:pathPattern,你可以添加任意个 data 标签,由于是 "或"的关系 ,因此,只要其中任意一个 data 匹配,系统就会选择你的 Activity 启动,当然,如果别的 Activity 也有相同的 data 标签,系统就会给用户弹出一个 Chooser Dialog。

path、pathPrefix、pathPattern 之间的区别:

  • path 用来匹配完整的路径,如:http://example.com/blog/abc.html,这里将 path 设置为 /blog/abc.html 才能够进行匹配;
  • pathPrefix 用来匹配路径的开头部分,拿上面的 Uri 来说,这里将 pathPrefix 设置为 /blog 就能进行匹配了;
  • pathPattern 用表达式来匹配整个路径,这里需要说下匹配符号与转义。
    匹配符号:
    * 用来匹配0次或更多,如:a* 可以匹配aaaaaa...
    . 用来匹配任意字符,如:. 可以匹配abc...
    因此 .* 就是用来匹配任意字符0次或更多,如:.*html 可以匹配 abchtmlchtmlhtmlsdf.html...
    转义:
    因为当读取 Xml 的时候,\ 是被当作转义字符的(当它被用作 pathPattern 转义之前),因此这里需要两次转义,读取 Xml 是一次,在 pathPattern 中使用又是一次。如:* 这个字符就应该写成 \\*\ 这个字符就应该写成 \\\\

mimeType 是用来匹配 Intent 的数据类型的。比如,当你使用 Intent.setType("text/plain") ,那么系统将会匹配到所有注册 android:mimeType="text/plain" 的 Activity。

在设置Intent的时候可以使用Intent.setType(), Intent.setData,Intent.setDataAndType() 这三个方法:

  • setType 调用后设置 mimeType,然后将 data 置为 null;
  • setData 调用后设置 data,然后将 mimeType 置为 null;
  • setDataAndType 调用后才会同时设置 data 与 mimeType。

另外需要注意的是,如果你在 data 标签,既设置了 mimeType 又设置了 scheme 之内的,那么你的 Intent 需要同时设置匹配的 data 与 mimeType 即调用 setDataAndType ,系统才能匹配到这个 Activity(即便你 mimeType 设置为 */* 也是如此)。当然,如果你没有设置 mimeType,那么调用 setData 进行匹配,如果你设置了任何的 mimeType 将不会匹配到该 Activity。

例子1:
如果我们想要匹配 http 以 .pdf 结尾的路径,使得别的程序想要打开网络 pdf 时,用户能够可以选择我们的程序进行下载查看。

我们可以将 scheme 设置为 http,pathPattern 设置为 .*\\.pdf,整个 intent-filter 设置为:

<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<data android:scheme="http" android:pathPattern=".*\\.pdf"></data>
</intent-filter>

如果你只想处理某个站点的 pdf,那么在 data 标签里增加 android:host="yoursite.com" 则只会匹配 http://yoursite.com/xxx/xxx.pdf, 但这不会匹配 www.yoursite.com,如果你也想匹配这个站点的话,你就需要再添加一个 data 标签,除了 android:host 改为 www.yoursite.com 其他都一样。

例子2:
如果我们做的是一个IM应用,或是其他类似于微博之类的应用,如何让别人通过 Intent 进行调用分享出现在选择框里呢?
我们只用注册 android.intent.action.SEND 与 mimeType 为 text/plain 或 */* 就可以了,整个 intent-filter 设置为:

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data mimeType="*/*" />
</intent-filter>

例子3:
如果我们做的是一个音乐播放软件,当文件浏览器打开某音乐文件的时候,使我们的应用能够出现在选择框里?

这类似于文件关联了,其实做起来跟上面一样,也很简单,我们只用注册 android.intent.action.VIEW 与 mimeType 为 audio/* 就可以了,整个 intent-filter 设置为:

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="audio/*" />
</intent-filter>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值