Intent中文的译名"意图",它用来完成的组件之间的通信,确切的讲,基本有两个作用:
1、可以启动另外一个组件。
2、可以携带少量数据传递给另外一个组件。
基本用例有:启动活动、启动服务、传递广播,不包括contentProvider,它使用Uri的方式来启动。
就拿启动活动来说,为什么不直接用startActivity(Class activityClass)的方式,这样更符合正常的思考方式。但是假如你需要传递其它信息,比如附加数据,或者隐式的启动一个组件(不指定具体组件类名),需要通过其它信息来定位,需要多个杂乱的方法来实现,另外是启动其它组件,如果服务、广播也同样需要如此;用Intent的方式提供一致的编程模型,把需要的信息都封装起来,更符合Java封装的特点。
Intent分为显式Intent和隐式Intent。
显式Intent:按名称(完全限定类名)指定要启动的组件,通常用来在自己应用中启动组件,这是因为你知道需要启动组件(活动或者服务)的类名。
隐式Intent:不指定特定的组件,而是声明要执行的常规操作,从而允许其它应用中的组件来处理它,可以实现跨应用组件的调用。
创建显式 Intent 启动 Activity 或服务时,系统将立即启动 Intent
对象中指定的应用组件。
创建隐式 Intent 时,Android 系统通过将 Intent 的内容与在设备上其他应用的清单文件中声明的 Intent 过滤器(intent-filter)进行比较,从而找到要启动的相应组件。如果 Intent 与 Intent 过滤器匹配,则系统将启动该组件,并将其传递给对象。如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。
图 1. 隐式 Intent 如何通过系统传递以启动其他 Activity 的图解:
[1] Activity A 创建包含操作描述的 Intent
,并将其传递给 startActivity()
。
[2] Android 系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。找到匹配项之后,[3] 该系统通过调用匹配 Activity(Activity B)的 onCreate()
方法并将其传递给Intent
,以此启动匹配 Activity,可以通过getIntent()方法获取这个Intent对象。
Intent 过滤器是应用清单文件中的一个表达式,它指定该组件要接收的 Intent 类型。例如,通过为 Activity 声明 Intent 过滤器,您可以使其他应用能够直接使用某一特定类型的 Intent 启动 Activity。同样,如果您没有为 Activity 声明任何 Intent 过滤器,则 Activity 只能通过显式 Intent 启动。
Intent根据类型、是否携带数据、启动标志,提供了多种属性设置,分别是:
显式:Component,就好比网红明确指定思聪为老公对象。
隐式:Action、Category、Data、Type,就好比要求是CEO、有钱、180、长的帅等属性。
携带数据:Extra
启动标志:Flag
Component(组件名称):要启动的组件名称。
这是可选项,但也是构建显式 Intent 的一项重要信息,这意味着 Intent 应当仅传递给由组件名称定义的应用组件。如果没有组件名称,则 Intent 是隐式的,且系统将根据其他 Intent 信息(例如,以下所述的操作、数据和类别)决定哪个组件应当接收 Intent。因此,如需在应用中启动特定的组件,则应指定该组件的名称。您可以使用目标组件的完全限定类名指定此对象,其中包括应用的软件包名称。如,com.example.ExampleActivity
。您可以使用setComponent()
、setClass()
、setClassName()
或Intent
构造函数设置组件名称。
如:
ComponentName comp = new ComponentName(MainActivity.this,SecondActivity.class);
Intent inent = new Intent();
intent.setComponent(comp);
可以通过构造函数简化为另一种形式:
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
而这方式是最常用的方式,但是往往会忽略了它是用来设置组件名称。
Action(操作):指定要执行的通用操作(例如,“查看”或“选取”)的字符串
您可以使用setAction()
或Intent
构造函数为 Intent 指定操作。
如果定义自己的操作,请确保将应用的软件包名称作为前缀。 例如:staticfinalString ACTION_TIMETRAVEL ="com.example.action.TIMETRAVEL";
对于广播 Intent,这是指已发生且正在报告的操作。操作在很大程度上决定了其余 Intent 的构成,特别是数据和 extra 中包含的内容。因为广播
本身就类似一个全局的监听器,所以它都是使用隐式Intent,通过系统层面向匹配到的接收器发送数据和 extra 中包含的内容。
Data(数据):引用待操作数据和/或该数据 MIME 类型的 URI(Uri
对象)。它虽然也是指数据,但是必须是Uri类型,所以不是传统意义上的数据,不过它依然可以解析为有用的信息,比如是一个URL(网址),如“http://www.google.com”,可以访问网页;可以解析为一个电话号码,如“tel:1234”,可以自动拨号。
创建 Intent 时,除了指定 URI 以外,指定数据类型(其 MIME 类型)往往也很重要。例如,能够显示图像的Activity可能无法播放音频文件,即便 URI 格式十分类似时也是如此。因此,指定数据的 MIME 类型有助于 Android 系统找到接收 Intent 的最佳组件。
要仅设置数据 URI,请调用setData()
。要仅设置 MIME 类型,请调用setType()
。如有必要,您可以使用setDataAndType()
同时显式设置二者。
若要同时设置 URI 和 MIME 类型,请勿调用setData()
和setType()
,因为它们会互相抵消彼此的值。请始终使用setDataAndType()
同时设置 URI 和 MIME 类型。
Category(类别):一个包含应处理 Intent 组件类型的附加信息的字符串。您可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。
CATEGORY_BROWSABLE
CATEGORY_LAUNCHER
有关类别的完整列表,请参阅 Intent
类描述。
您可以使用 addCategory()
指定类别。
以上列出的这些属性(组件名称、操作、数据和类别)表示 Intent 的既定特征。通过读取这些属性,Android 系统能够解析应当启动哪个应用组件。
但是,Intent 也有可能会一些携带不影响其如何解析为应用组件的信息。Intent 还可以提供:
Extra(附加数据): 携带完成请求操作所需的附加信息的键值对。正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的附加数据。
您可以使用各种putExtra()
方法添加附加数据,每种方法均接受两个参数:键名和值。您还可以创建一个包含所有附加数据的Bundle
对象,然后使用putExtras()
将Bundle
插入Intent
中。
例如,使用ACTION_SEND
创建用于发送电子邮件的 Intent 时,可以使用EXTRA_EMAIL
键指定“目标”收件人,并使用EXTRA_SUBJECT
键指定“主题”。
Intent
类将为标准化的数据类型指定多个EXTRA_*
常量。如需声明自己的附加数据键(对于应用接收的Intent),请确保将应用的软件包名称作为前缀。例如:
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";Flag(启动标志): 在
Intent
类中定义的、充当 Intent 元数据的标志。标志可以指示 Android 系统如何启动 Activity(例如,Activity 应属于哪个 任务),以及启动之后如何处理(例如,它是否属于最近的 Activity 列表)。
intent-filte 配置
要公布应用可以接收哪些隐式 Intent,请在清单文件(AndroidManifest.xml)中使用<
intent-filter>
元素为每个应用组件声明一个或多个Intent过滤器。每个Intent过滤器均根据 Intent的操作(action)、数据(data)和类别(category)指定自身接受的 Intent 类型。仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件
每个Intent过滤器均由应用清单文件中的<intent-filter>
元素定义,并嵌套在相应的应用组件(例如,<
activity>
元素)中。在<
intent-filter>
内部,您可以使用以下三个元素中的一个或多个指定要接受的 Intent 类型:
在 android:
name
属性中,声明接受的 Intent 操作。该值必须是操作的文本字符串值,而不是类常量。它表示该Intent所要完成的一个抽象动作。
<
data />
使用一个或多个指定数据URI(
scheme
、
host
、
port
、
path
等)各个方面和 MIME 类型的属性,声明接受的数据类型。 在AndroidManifest.xml文件中为组件声明Data、Type属性都是通过该元素,它的格式如下:
android:scheme = ""
android:host = ""
android:port = ""
android:path = ""
android:pathPrefix = ""
android:pathPattern = "" /> 其中scheme、hots、port、path都是属于Uri的属性。
;
在 android:
name
属性中,声明接受的 Intent 类别。该值必须是操作的文本字符串值,而不是类常量。它用于为action增加额外的附加类别信息,一般与action结合使用。 当程序中创建Intent时,该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量的组件,所以在被启动Activity对应的配置元素的ntent-filter>:如果该组件声明多个intent-filter子元素,只要隐式Intent对象的属性能够匹配其中一个就可以启动该组件;
在intent-filter下面可以声明
:而data子元素不是值完全相同才算匹配成功,如果data子元素中只指定了android:scheme属性,那么只要Intent对象中data属性的scheme部分与android:scheme属性值相同,既即可启动该组件;如果data子元素中只指定了android:scheme、android:host属性,那么只要Intent对象中data属性的scheme、host部分与android:scheme、android:host属性值相同,即可启动该组件,依次类推。
参考:
1、Google Guide:Intents and Intent Filter
2、疯狂Android讲义:5.1 Intent对象简述 5.2 Intent属性及intent filter配置。