目录
Intent 和 Intent 过滤器
Intent是消息传递对象,我们可以用来从其他组件请求操作,Intent可以通过多种方式促进组件之间的通信,但是主要的使用方式有以下三种:
- 启动Activity【
startActivity(Intent intent)
】 - 启动Service【
startService(Intent intent)
】 - 启动广播【
sendBroadCast(Intent intent)
】【sendBroadOrderedCast(Intent intent)
】
Intent类型
Intent分为两种类型
通过提供完整的应用报名或者完全限定的组件类名来指定可处理Intent的应用。
不会指定特定的组件,而是声明要执行的特定操作。
使用隐式Intent时,Android系统会将Intent中的内容与设备上其他应用的清单文件中声明的Intent过滤器进行比较,从而找到要启动的相应组件,如果匹配,则会启动该组件,并向其传递Intent对象,如果有多个过滤器匹配则显示对话框,支持用户选择想要使用的应用。如果该intent没有申明任何过滤器这只能通过显示intent启动。
注意:尽量不要使用隐式intent启动服务,因为用户不知道启动了哪些服务。
构建Intent
Intent对象可以设置以下信息
设置要启动组件的名称,当设置该属性之后,该Intent只能启动对应的组件,如果没有设置组件名称,则为隐式Intent,可以使用 setComponent()
、setClass()
、setClassName()
,或 Intent 构造函数
设置组件名称。
指定要执行的通用操作,可以使用setAction
函数为Intent指定操作。如ACTION_VIEW
和ACTION_SEND
等
引用待操作数据和/或该数据 MIME
类型的 URI
(Uri 对象)。提供的数据类型通常由 Intent 的操作决定。例如,如果操作是 ACTION_EDIT
,则数据应包含待编辑文档的 URI
。
一个包含应处理 Intent 组件类型的附加信息的字符串。可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。以下是一些常见类别:
CATEGORY_BROWSABLE
目标 Activity 允许本身通过网络浏览器启动,以显示链接引用的数据,如图像或电子邮件。CATEGORY_LAUNCHER
该 Activity 是任务的初始 Activity,在系统的应用启动器中列出。
可以使用setCateGory()添加类别。
(组件名称、操作、数据和类别)表示 Intent 的既定特征。通过读取这些属性,Android 系统能够解析应当启动哪个应用组件。
-
Extra
可以使用各种 putExtra() 方法添加 extra 数据,每种方法均接受两个参数:键名和值。还可以创建一个包含所有 extra 数据的 Bundle 对象,然后使用 putExtras() 将 Bundle 插入 Intent 中。 -
标志
可以用来指定启动目标组件的方式,如:
FLAG_ACTIVITY_SINGLE_TOP(相当于设置为SingleTop模式)
显示Intent
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
//显示启动服务
startService(downloadIntent);
隐式Intent
Intent sendIntent = new Intent();
//执行操作
sendIntent.setAction(Intent.ACTION_SEND);
//携带数据
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
//设置数据类型
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
//为了确保当没有匹配的intent-fliter时,不会出现异常
startActivity(sendIntent);
}
强制使用应用选择器
Intent sendIntent = new Intent(Intent.ACTION_SEND);
String title = getResources().getString(R.string.chooser_title);
Intent chooser = Intent.createChooser(sendIntent, title);
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
接收隐式Intent
要公布应用可以接收哪些隐式 Intent,请在清单文件中使用 <intent-filter>
元素为每个应用组件声明一个或多个 Intent 过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接受的 Intent 类型。仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。
可以使用以下三个元素中的一个或多个指定要接受的 Intent 类型
<action>
在 name 属性中,声明接受的 Intent 操作。该值必须是操作的文本字符串值,而不是类常量。<data>
使用一个或多个指定数据 URI(scheme、host、port、path)各个方面和 MIME 类型的属性,声明接受的数据类型。<categroy>
在 name 属性中,声明接受的 Intent 类别。该值必须是操作的文本字符串值,而不是类常量。
过滤器示例
<activity android:name="MainActivity">
<!-- This activity is the main entry, should appear in app launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- This activity handles "SEND" actions with text data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
可以创建一个包括多个 、 或 实例的过滤器。创建时,需确定组件能够处理这些过滤器元素的任何及所有组合。
如需仅以操作、数据和类别类型的特定组合来处理多种 Intent,则需创建多个 Intent 过滤器。
系统通过将 Intent 与所有这三个元素进行比较,根据过滤器测试隐式 Intent。隐式 Intent 若要传递给组件,必须通过所有这三项测试。如果 Intent 甚至无法匹配其中任何一项测试,则 Android 系统不会将其传递给组件。但是,由于一个组件可能有多个 Intent 过滤器,因此未能通过某一组件过滤器的 Intent 可能会通过另一过滤器。
Intent解析
当收到隐式 Intent 以启动 Activity 时,系统会根据以下三个方面将该 Intent 与 Intent 过滤器进行比较,搜索该 Intent 的最佳 Activity:
- 操作
- 数据(URI 和数据类型)
- 类别
下文根据应用的清单文件中的 Intent 过滤器声明,描述 Intent 如何与相应的组件匹配。
操作测试
要指定接受的 Intent 操作,Intent 过滤器既可以不声明任何 <action>
元素,也可以声明多个此类元素,如下例所示:
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.VIEW" />
...
</intent-filter>
要通过此过滤器,您在 Intent 中指定的操作必须与过滤器中列出的某一操作匹配。
如果该过滤器未列出任何操作,则 Intent 没有任何匹配项,因此所有 Intent 均无法通过测试。但是,如果 Intent 未指定操作,则只要过滤器内包含至少一项操作,就可以通过测试。
类别测试
要指定接受的 Intent 类别,Intent 过滤器既可以不声明任何 元素,也可以声明多个此类元素,如下例所示:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
...
</intent-filter>
若要使 Intent 通过类别测试,则 Intent 中的每个类别均必须与过滤器中的类别匹配。反之则未必然,Intent 过滤器声明的类别可以超出 Intent 中指定的数量,且 Intent 仍会通过测试。因此,不含类别的 Intent 应当始终会通过此测试,无论过滤器中声明何种类别均是如此。
数据测试
要指定接受的 Intent 数据,Intent 过滤器既可以不声明任何 元素,也可以声明多个此类元素,如下例所示:
<intent-filter>
<data android:mimeType="video/mpeg" android:scheme="http" ... />
<data android:mimeType="audio/mpeg" android:scheme="http" ... />
...
</intent-filter>