之前写过一篇Intent的博客,主要说了一下隐式意图。 传送门:《Android -- Intent》

Intent对象构成

Component name、Action、Data、Category、Extras、Flags

Component name

Component name即组件名称,是要处理这个Intent对象的组件名称。

组件名称对象由ComponentName类来封装,组件名称包含包名称和类名称,被声明在AndroidManifest.xml文件中。

组件名称通过 setComponent(),setClass(),setClassName()设置,通过getComponent()获取。

需要注意的是Component name是一个可选项,如果被设置,那么Intent对象就显式指定了要转向的组件,如果没有被设置,则Intent对象需要根据其他信息进行筛选查找。

Action

Action是指Intent要完成的动作,是一个字符串常量。

Intent类中有很多预定义的常量,为了一些通常的动作;还有一些定义在Android API的其他地方。也可以自己定义Action常量,自定义的常量需要加上你的应用的包名作为前缀。

Action在很大程度上决定了Intent的其他部分是如何构造的,尤其是 data 和 extras域。(就好像函数名会决定着参数值和返回值一样。)所以Action的名字应该尽可能具体,并且它们应该和Intent中的其他域紧密结合。

使用 setAction() 和 getAction()来设置和读取Action属性。

Data

Data属性是执行动作的URI和MIME类型,不同的动作有不同的数据规格。

比如,Action是ACTION_EDIT时,数据域将是文档的URI;Action是ACTION_CALL时,数据域是 tel: URI ,带有要拨打的电话号码;如果Action是 ACTION_VIEW,则数据域是http: URI。

当匹配intent和能够处理intent所带的数据的组件时,知道数据类型(MIME类型)是很重要的。比如,一个展示图像的组件不应该被叫去播放一个音频。

很多情况下,从URI可以看出数据类型,比如content: URIs,表示数据是在设备上,但是是由content provider控制。

数据类型也可以显式指定,比如setData()方法指定数据为URI,setType() 指定为MIME type,setDataAndType() 指定它既为URI又为MIME type。读取的时候URI用getData(),MIME type用getType()。

Category

Category是一个字符串,提供了额外的信息,有关于能够处理这个Intent对象的组件种类。

一个Intent对象中可以包含任意数量的category描述信息。

与category相应的方法有添加addCategory()、移除removeCategory() 和获取所有category getCategories() 。

Extras

传递给Intent的额外数据,以Bundle的形式定义,就是一些键值对。就好像一些动作和特定的数据URI对应,一些动作和特定的extras对应。

比如ACTION_TIMEZONE_CHANGED intent对象有一个 "time-zone"的extra来确认新的时区;

ACTION_HEADSET_PLUG有一个"state" extra表示耳机是否插入,还有一个 "name" extra关于耳机类型;

如果你要设计一个SHOW_COLOR动作,那么extra中应该包含颜色值。

Intent对象有一系列的putXXX()函数用于放入各种数据类型,相应的也有一系列的getXXX()函数用于读取数据。

实际上,数据可以被作为一个Bundle对象被使用,利用 putExtras() 和 getExtras() 方法。

Flags

各种类型的Flag。很多是用来指定Android系统如何启动activity,还有启动了activity后如何对待它。所有这些都定义在Intent类中。

Intent filter

为了告知系统哪一些隐式的intent可以被处理,activity,service和broadcast receiver拥有一个或多个intent filter。

每一个filter描述了组件的一种能力,和一个这个组件愿意接收的intent的集合。它实际上的效果是过滤了特定类型的intent,将不想要的intent排除在外,但是也只能排除不想要的隐式类型的intent,显式的intent可以直接被传递到它的目标对象,不管它包含什么,filter是不会被查询的。

但是一个隐式的intent只能在能够通过这个组件的filter之一的时候传递到这个组件。

一个组件对于它可以做的各种工作拥有各种独立的filter。

一个intent filter就是一个IntentFilter类的对象,但是,由于Android系统必须在启动一个组件前知道它的能力,intent filter通常不是在Java代码中建立的,而是在应用的manifest文件中(AndroidManifest.xml),作为<intent-filter> 元素。

一个例外的情况就是broadcast receiver的filter,它们是通过Context.registerReceiver()方法动态注册的,它们将会被直接作为IntentFilter对象创建。

当一个Intent对象和一个intent filter进行测试时,Intent对象中只有三个方面会被参考:

  • action
  • data(URI和数据类型)
  • category

当决议那个组件接收intent时,extras和flags是不起作用的。

一个filter含有与Intent对象中的action,data,category平行的域,一个隐式的intent将会测试所有这三个域

为了传递到含有filter的组件,intent对象必须通过所有这三个测试。

如果其中的一个测试失败了,Android系统将不会把这个intent对象传递到这个组件,至少不会是基于那个filter的组件

然而,由于一个组件可以拥有多个intent filter,一个intent对象可能没有通过其中的一个filter,但是它可能通过另一个。

Code Action

在manifest中,<intent-filter>元素将动作作为其<action>子元素列出:

<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>

一个filter可以列出多个动作,这个列表不能为空,即一个filter应该至少包含一个动作否则它将会阻挡任何的intent

为了通过这个测试,intent对象中指定的动作应该和列出的动作之一匹配,如果intent对象或filter没有指定动作,结果将会如下:

1.如果是filter没有列出任何动作,没有东西让intent来匹配,所以所有的intent都将会在测试中失败。没有任何intent可以通过这个测试。

2.另一方面,如果一个intent对象没有指定动作,那它将自动地通过测试。(只要filter中含有至少一个动作)。

Code Category

<intent-filter>也将分类作为其子元素列出,如

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

如果一个intent对象想通过category,那么在intent对象中的每一个分类都必须和filter中的一个分类匹配

Filter可以列出多余的分类,但是不能忽略intent中的任何一个分类。

原则上来说,一个不带有任何category的intent对象应该总是能够通过测试。但是有一个例外,Android将所有传入startActivity()方法的隐式intent看作它们至少含有一个category: "android.intent.category.DEFAULT" (the CATEGORY_DEFAULT constant)。

所以,想要收到隐式intent对象的activity必须在它们的intent filter中包含 "android.intent.category.DEFAULT" 。(包含"android.intent.action.MAIN" 和 "android.intent.category.LAUNCHER"的filter是一个例外,它们可以包含"android.intent.category.DEFAULT",但是它们没有必要这样做。)

Code Data

和动作和分类一样,数据也是作为子标签出现,也可以不出现或出现多次。如:

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

每一个<data>元素可以指定一个URI和一个数据类型(MIME media type)。

每一个URI包含下列属性:scheme, host, port, path (如:scheme://host:port/path)

当一个intent对象中的URI和filter中的URI比较时,它仅仅和filter中实际提到的URI部分进行比较。比如,一个filter仅仅指定了scheme,那么所有有那个scheme的URI都和这个filter匹配。

Filter中的path可以包含通配符(wildcards)。

<data>元素中的type属性指定了数据的MIME type,它在filter中比URI更常见。

Intent对象和filter都可以使用通配符*去表示子类型,如"text/*" or "audio/*" — indicating any subtype matches。

数据测试需要测试URI和数据类型,规则如下:

a.一个intent对象,如果既不包含URI,也不包含数据类型,那么仅当filter也都不包含时,可以通过测试。

b.如果一个intent对象仅包含一个URI,不包含数据类型,(并且从URI中也不能得到数据类型),那么仅当这个URI和filter中的URI匹配,并且filter中也不包含数据类型时,可以通过测试。(This will be the case only for URIs like mailto: and tel: that do not refer to actual data.)

c.一个intent对象如果只包含数据类型不包含URI,那么仅当filter包含同样的数据类型并且不包含任何URI时可以通过测试。

d.一个intent对象如果同时包含URI和数据类型,(或者是可以从URI中推断出的数据类型),那么仅当它的数据类型和filter中的一个数据类型匹配时它可以通过数据类型部分的测试,如果要通过URI部分的测试,一种情况是它的URI和filter中的匹配,另一种情况是intent包含有content:或者file:URI而filter不包含URI。换句话说,如果一个filter只指定了数据类型,组件是预定义地支持content:或者file:数据的。

  如果一个intent可以通过多个activity或service的filter,用户将被询问,到底要选择哪个组件来启动;如果没有目标被发现,将会产生一个异常。

我是天王盖地虎的分割线

更多相关文章

  1. android事件处理
  2. ReactNative 在用react-navigation组件时,没有 navigator.getCurr
  3. View类的XML属性、相关方法及说明
  4. Android的绘制文本对象FontMetrics的介绍及绘制文本
  5. 2011.07.12(2)——— android Messenger 跨进程通信
  6. android IPC机制
  7. android 内存泄漏的分析
  8. 随笔10
  9. Android五大布局对象

随机推荐

  1. android 9.0 收到通知消息亮屏
  2. android 设置标题
  3. 移动端区分安卓系统和ios系统
  4. Android(安卓)Retrofit 2.0框架上传图片
  5. 查看已經下載好ANDROID源碼是什麽版本號
  6. MacOS 下Android Studio NDK 环境搭建与
  7. Android HapticFeedback(震动反馈)介绍
  8. [置顶] android中常见的内存泄露场景
  9. android的sdcard文件的读取和保存详细介
  10. Android-使用Junit单元测试