文章目录
https://developer.android.com/reference/android/content/Intent
java.lang.Object
↳ android.content.Intent
它基本上是一个被动数据结构,其中包含要执行的动作的抽象描述。
结构
主要属性
action:要执行的常规操作,例如ACTION_VIEW,ACTION_EDIT,ACTION_MAIN等。这些字符串使用 Java 风格的作用域,以确保它们是唯一的。例如,ACTION_VIEW 称为 android.intent.action.VIEW
data:待操作数据 and/or 该数据 MIME 类型的 URI(Uri 对象)。提供的数据类型通常由 Intent 的 action 决定。例如,如果 action 是 ACTION_EDIT,则数据应包含待编辑文档的 URI。
action & data 的一些示例:
ACTION_VIEW & content://contacts/people/1:显示有关其标识符为“ 1”的人员的信息。
ACTION_EDIT & content://contacts/people/1:编辑有关其标识符为“ 1”的人员的信息。
ACTION_VIEW & content://contacts/people/:显示人员列表,用户可以浏览。
ACTION_DIAL & content://contacts/people/1:显示电话拨号器,并填入人员。
ACTION_DIAL & tel:123:显示带有给定号码的电话拨号器。
辅助属性
category:提供有关要执行的操作的其他信息。例如,CATEGORY_LAUNCHER 意味着它应该在启动器中作为顶级应用程序出现,而 CATEGORY_ALTERNATIVE 意味着它应该被包括在用户可以对数据执行的替代操作列表中。
type:指定意图数据的显式类型(MIME 类型)。通常,如果使用了 URI 设置 data,类型可以从 URI 中推断出来的。设置此属性,可以不需推断而强制使用显式类型。
component:指定用于意图的组件类的显式名称。通常,这是通过查看意图中的其他信息(taction、data/type 和 categories)并将其与可以处理它的组件进行匹配来确定的。如果设置了此属性,则不需进行匹配而直接使用此组件。指定此属性,所有其他 Intent 属性将变为可选。
extras:这是所有其他信息的 Bundle 包。这可用于向组件提供扩展信息。例如,如果我们有发送电子邮件的动作,我们还可以在此处包括额外的数据,以提供主题,正文等。此外,它携带完成请求操作所需的附加信息的键值对,正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的 extra。例如,使用 ACTION_SEND 创建用于发送电子邮件的 Intent 时,可以使用 EXTRA_EMAIL 键指定目标收件人,并使用 EXTRA_SUBJECT 键指定主题。
以下是一些操作的示例:
ACTION_MAIN & category CATEGORY_HOME:启动主屏幕。
ACTION_GET_CONTENT & MIME type vnd.android.cursor.item/phone:显示人们的电话号码列表,允许用户浏览并选择其中一个并将其信息返回。
ACTION_GET_CONTENT & MIME type */* & category CATEGORY_OPENABLE:显示所有可以使用 ContentResolver#openInputStream(Uri) 打开的数据选择器,让用户选择其中之一,然后选择其中的一些数据,并将结果 URI 返回给调用方。例如,可以在电子邮件应用程序中使用它来允许用户选择一些要包含为附件的数据。
data(URI) & type(MIME) 的区别
创建 Intent 时,除了指定 URI 以外,指定数据类型(其 MIME 类型)往往也很重要。例如,能够显示图像的 Activity 可能无法播放音频文件,即便 URI 格式十分类似时也是如此。因此,指定数据的 MIME 类型有助于 Android 系统找到接收 Intent 的最佳组件。但,有时 MIME 类型可以从 URI 中推断得出,特别当数据是 content: URI 时尤其如此。content: URI 表明数据位于设备中,且由 ContentProvider 控制,这使得数据 MIME 类型对系统可见。
要仅设置数据 URI,请调用 setData()。要仅设置 MIME 类型,请调用 setType()。如有必要,您可以使用 setDataAndType() 同时显式设置二者。
注意:若要同时设置 URI 和 MIME 类型,请勿调用 setData() 和 setType(),因为它们会互相抵消彼此的值。请始终使用 setDataAndType() 同时设置 URI 和 MIME 类型。
实例
在新建应用时,第一个 Activity 有如下信息:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
MAIN 动作表示该 Activity 是程序的的入口点,程序启动时即创建(不要求传递数据来访问),程序必须有一个 MAIN Activity
LAUNCHER 类别表示该程序应在 Launcher 应用中以图标形式列出。两者配合使用才能在 Launcher 启动该程序。例如,ACTION_MAIN 与 CATEGORY_CAR_DOCK 表示的活动,在用户将手机设置为制造商提供的汽车坞站模式时能作为候补程序显示。
https://stackoverflow.com/questions/25219551/what-is-the-meaning-of-android-intent-action-main
调用
显式调用:指定了特定组件的名称,Intent 中这一字段是 ComponentName 对象。您可以使用目标组件的完全限定类名指定此对象,其中包括应用的软件包名称。例如,com.example.ExampleActivity。您可以使用 setComponent()、setClass()、setClassName(),或 Intent 构造函数设置组件名称。
隐式调用:未指明组件,提供了其他类别信息
隐式 Intent 如何通过系统传递以启动其他 Activity:
[1] Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()。
[2] Android 系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。找到匹配项。
[3] 该系统通过调用匹配 Activity (Activity B) 的 onCreate() 方法并将其传递给 Intent,以此启动匹配 Activity。
隐式 Intent 示例:分享内容给其他应用
注意:用户可能没有任何应用处理您发送到 startActivity() 的隐式 Intent。或者,由于配置文件限制或管理员执行的设置,可能无法访问应用。如果发生这样的情况,调用失败,出现 ActivityNotFoundException 异常,应用也会崩溃。要验证 Activity 是否会接收 Intent,请对 Intent 对象调用 resolveActivity()。如果结果为非空,则至少有一个应用能够处理该 Intent,并且可以安全调用 startActivity()。如果结果为空,不要使用该 Intent。如有可能,您应停用发出该 Intent 的功能。
以下示例说明如何验证 Intent 是否解析为 Activity。此示例没有使用 URI,但已声明 Intent 的数据类型,用于指定 extra 携带的内容。
// Create the text message with a string
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) {
startActivity(sendIntent);
}
示例方法:
public void viewUrl(String url, String mimeType) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), mimeType);
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
if (Config.LOGD) {
Log.d(LOGTAG, "activity not found for " + mimeType + " over " + Uri.parse(url).getScheme(), e);
}
}
}
}
另一种验证方式:调用 queryIntentActivities() 以获取能够处理您的 Intent 的 Activity 列表。如果返回的 List 不为空,则您可以安全地使用该 Intent。
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
queryIntentActivities() 将返回能够执行作为参数传递的 Intent 中列出的所有 Activity,而 queryIntentServices() 则可返回类似的一系列服务。这两种方法均不会激活组件;而只是列出能够响应的组件。对于广播接收器,有一种类似的方法:queryBroadcastReceivers()。
启用应用选择器对话框
如果要执行的操作可以由多款应用处理并且用户可能希望每次都使用不同的应用(例如,“分享”操作,用户可能有多款应用可用来分享内容),则您应明确显示选择器对话框。选择器对话框会强制用户选择每次要为相应操作使用的应用(用户无法针对该操作选择默认应用)。
Intent intent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);
// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
这会显示一个对话框,其中包含可响应 Intent 的应用列表,并将提供的文本用作对话框标题。
https://developer.android.com/training/basics/intents/sending
解析
https://developer.android.com/guide/components/intents-filters#Resolution
在清单文件中使用 <intent-filter>
元素为每个应用组件声明一个或多个 Intent 过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接受的 Intent 类型。仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。
Intent Resolution 会对 Intent 与已安装的应用程序包中的所有 <intent-filter>
描述进行匹配,解析到符合 Intent 的组件供用户启动,在 PackageManager 上能查询出可处理该意图的组件。
用于解析的三个元素:<action>
、<data>
和 <category>
,隐式 Intent 若要传递给组件,必须通过这三项检测。如果 Intent 无法匹配过滤器提供的任何一项,则 Android 系统不会将其传递给组件,其中 <data>
包含了 MIME 和 URI 两项检验。
MIME 和 URI 在 Intent 和过滤器间不一定完全匹配,有以下例外:
MIME 如果未在 Intent 中提供,则可以根据 URI 推断(可能无法推断得出,而匹配过滤器 MIME 失败)。
如果过滤器只是列出 MIME 类型,则假定组件支持 content:
和 file:
数据,说明能从文件中或内容提供程序处获得组件的数据,Intent 使用此种 URI 可以匹配。
Intent 使用不是 content:
架构的 URI,且没有提供类型,将考虑使用 http:
或 mailto:
之类的架构。
注意:如果 Intent 指定 URI 或 MIME 类型,而 <intent-filter>
没有 <data>
元素则匹配失败。
由于大部分可用数据均由内容提供程序分发,因此指定数据类型(而非 URI)的过滤器也许最为常见。
另一常见的配置是具有架构和数据类型的过滤器。例如,下文中的 <data>
元素向 Android 指出,组件可从网络中检索视频数据以执行操作:
<intent-filter>
<data android:scheme="http" android:mimeType="video/*" />
...
</intent-filter>
注意:要接收隐式 Intent,必须将 CATEGORY_DEFAULT 类别包括在 Intent 过滤器中。方法 startActivity()
和 startActivityForResult()
默认按照 CATEGORY_DEFAULT 类别的方式处理所有 Intent。如果未在 Intent 过滤器中声明此类别,则隐式 Intent 不会解析为您的 Activity。
<data>
解析
每个 <data>
元素均可指定 URI 结构和数据类型(MIME 媒体类型)。URI 的每个部分都是一个单独的属性:scheme、host、port 和 path:
<scheme>://<host>:<port>/<path>
下例所示为这些属性的可能值:
content://com.example.project:200/folder/subfolder/etc
在此 URI 中,架构是 content,主机是 com.example.project,端口是 200,路径是 folder/subfolder/etc。
在 <data>
元素中,上述每个属性均为可选,但存在依赖关系:主机以来与架构、端口依赖于主机,路径依赖于架构和主机,缺少以来的属性无效。
注意:路径规范可以包含星号通配符 (*),因此仅需部分匹配路径名即可。
范例
查看 / 编辑目录、选择数据返回
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
这声明了活动可以在便签目录上执行的操作。支持的类型由 <type>
标记给出,即是 vnd.android.cursor.dir/vnd.google.note
类型,是具有零个或多个 (dir 类型是个集合) 包含记事本数据 (vnd.google.note) 的游标。
该活动允许用户查看或编辑数据目录(通过 VIEW 和 EDIT 操作),或选择特定的便签笔记并将其返回给请求者(通过 PICK 操作)。注意提供 DEFAULT 类别:Context#startActivity
方法在未明确指定其组件名称时解析活动是必需的。
关于 vnd.android.cursor.dir
,见 MIME。
选择特定类型数据返回
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
vnd.android.cursor.item/vnd.google.note
类型,是包含一个(item 类型)记事本数据 (vnd.google.note) 的游标。
GET_CONTENT 操作类似于 PICK 操作,不同的是,在这里,调用方指定他们想要的数据类型,以便在相应的控件中展示,而不是用户将要从中选择的数据类型。
查看 / 编辑数据
<intent-filter android:label="@string/resolve_edit">
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
插入新数据到目录中
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
INSERT 操作在便笺目录上执行,用户运行活动以创建新的空便笺数据,然后将其添加到内容提供者中,等待 EDIT 操作。
编辑标题
<intent-filter android:label="@string/resolve_title">
<action android:name="com.android.notepad.action.EDIT_TITLE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.ALTERNATIVE" />
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
CATEGORY_ALTERNATIVE:
支持此类别意味着您希望您的活动显示在用户可以执行的一组替代操作中,通常作为当前活动的选项菜单的一部分。您通常会希望在此操作的 <intent-filter>
中包含一个特定的标签,向用户描述它的作用。
具有此类别的IntentFilter的操作很重要,因为它描述了目标将执行的特定操作。通常,这不应该是一般动作(例如ACTION_VIEW,而应是特定名称,例如“com.android.camera.action.CROP”。对于用户而言,只会显示任何特定动作的一种替代形式,因此请使用特定动作这样可以确保显示您的替代项,同时还允许其他应用程序提供其对特定操作的替代。
CATEGORY_SELECTED_ALTERNATIVE:
设置是否应将活动视为用户当前选择的数据的替代选择操作。这类似于CATEGORY_ALTERNATIVE,但用于显示用户可以选择的项目列表的活动中,从而为用户提供了将对其执行的默认操作的替代方法。