视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Android中的Intent详细讲解
2025-09-30 22:39:36 责编:小OO
文档


在一个Android应用中,主要是由四种组件组成的,这四种组件可参考“Android应用的构成”。

而这四种组件是的,它们之间可以互相调用,协调工作,最终组成一个真正的Android应用。

在这些组件之间的通讯中,主要是由Intent协助完成的。

Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。

因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。

例如,在一个联系人维护的应用中,当我们在一个联系人列表屏幕(假设对应的Activity为listActivity)上,点击某个联系人后,希望能够跳出此联系人的详细信息屏幕(假设对应的Activity为detailActivity)

为了实现这个目的,listActivity需要构造一个 Intent,这个Intent用于告诉系统,我们要做“查看”动作,此动作对应的查看对象是“某联系人”,然后调用startActivity (Intent intent),

将构造的Intent传入,系统会根据此Intent中的描述,到ManiFest中找到满足此Intent要求的Activity,系统会调用找到的Activity,即为detailActivity,最终传入Intent,detailActivity则会根据此Intent中的描述,执行相应的操作。

一、抽象描述要描述什么

在Android参考文档中,对Intent的定义是执行某操作的一个抽象描述(确实很抽象)。我们先来看看这里的抽象描述,到底描述了什么。

首先,是要执行的动作(action)的一个简要描述,如VIEW_ACTION(查看)、EDIT_ACTION(修改)等,Android为我们定义了一套标准动作:

复制内容到剪贴板

代码:

MAIN_ACTION

VIEW_ACTION

EDIT_ACTION

PICK_ACTION

GET_CONTENT_ACTION

DIAL_ACTION

CALL_ACTION

SENDTO_ACTION

ANSWER_ACTION

INSERT_ACTION

DELETE_ACTION

RUN_ACTION

LOGIN_ACTION

CLEAR_CREDENTIALS_ACTION

SYNC_ACTION

PICK_ACTIVITY_ACTION

WEB_SEARCH_ACTION

此外,我们还可以根据应用的需要,定义我们自己的动作,并可定义相应的Activity来处理我们的自定义动作。

其次,是执行动作要操作的数据(data),Android中采用指向数据的一个URI来表示,如在联系人应用中,一个指向某联系人的URI可能为:content://contacts/1。

这种URI表示,通过 ContentURI这个类来描述,具体可以参考android.net.ContentURI类的文档。

以联系人应用为例,以下是一些action / data对,及其它们要表达的意图:

复制内容到剪贴板

代码:

VIEW_ACTION content://contacts/1-- 显示标识符为"1"的联系人的详细信息

EDIT_ACTION content://contacts/1-- 编辑标识符为"1"的联系人的详细信息

VIEW

_ACTION content://contacts/-- 显示所有联系人的列表

PICK_ACTION content://contacts/-- 显示所有联系人的列表,并且允许用户在列表中选择一个联系人,然后把这个联系人返回给父activity。例如:电子邮件客户端可以使用这个Intent,要求用户在联系人列表中选择一个联系人

另外,除了action和data这两个重要属性外,还有一些附加属性:

category(类别),被执行动作的附加信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。

type(数据类型),显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

component(组件),指定Intent的的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。

extras(附加信息),是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

总之,action、 data/type、category和extras 一起形成了一种语言。

这种语言使系统能够理解诸如“查看某联系人的详细信息”之类的短语。

随着应用不断的加入到系统中,它们可以添加新的action、 data/type、category来扩展这种语言。

应用也可以提供自己的Activity来处理已经存在的这样的“短语”,从而改变这些“短语”的行为。

二、Android如何解析Intent

在应用中,我们可以以两种形式来使用Intent:

•直接Intent:指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context, Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。

•间接Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。

对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将 Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Inte

nt,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的,判断方法如下:

•如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配;

•如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。

•如果Intent中的数据不是content: 类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme (比如 http: 或者mailto: ) 进行匹配。同上,Intent 的scheme必须出现在目标组件的scheme列表中。

•如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

三、应用例子

以下,以Android SDK中的便笺例子来说明,Intent如何定义及如何被解析。这个应用可以让用户浏览便笺列表、查看每一个便笺的详细信息。

xml 代码

复制内容到剪贴板

代码:

xmlns:android="http://schemas.android.com/apk/res/android"

package="com.google.android.notepad">

android:icon="@drawable/app_notes"

android:label="@string/app_name">

class="NotePadProvider"

android:authorities="com.google.provider.NotePad"

/>

class=".NotesList"

android:label="@string/title_notes_list">

android:value="android.intent.action.MAIN"

/>

android:value="android.intent.category.LAUNCHER"

/>

android:value="android.intent.action.VIEW"

/>

android:value="android.intent.action.EDIT"

/>

android:value="android.intent.action.PICK"

/>

android:value="android.intent.category.DEFAULT"

/>

android:value="vnd.android.cursor.dir/vnd.google.note"

/>

android:value="android.intent.action.GET_CONTENT"

/>

android:value="android.intent.category.DEFAULT"

/>

android:value="vnd.android.cursor.item/vnd.google.note"

/>

class=".NoteEditor"

android:label="@string/title_note">

android:label="@string/resolve_edit">

android:value="android.intent.action.VIEW"

/>

android:value="android.intent.action.EDIT"

/>

android:value="android.intent.category.DEFAULT"

/>

android:value="vnd.android.cursor.item/vnd.google.note"

/>

android:

value="android.intent.action.INSERT"

/>

android:value="android.intent.category.DEFAULT"

/>

android:value="vnd.android.cursor.dir/vnd.google.note"

/>

class=".TitleEditor"

android:label="@string/title_edit_title"

android:theme="@android:style/Theme.Dialog">

android:label="@string/resolve_title">

android:value="com.google.android.notepad.action.EDIT_TITLE"

/>

android:value="android.intent.category.DEFAULT"

/>

android:value="android.intent.category.ALTERNATIVE"

/>

android:value="android.intent.category.SELECTED_ALTERNATIVE"

/>

android:value="vnd.android.cursor.item/vnd.google.note"

/>

例子中的第一个Activity是com.google.android.notepad.NotesList,它是应用的主入口,提供了三个功能,分别由三个 intent-filter进行描述:

1、第一个是进入便笺应用的顶级入口(action为android.app.action.MAIN)。类型为android.app.category.LAUNCHER表明这个Activity将在Launcher中列出。

2、第二个是,当type为vnd.android.cursor.dir/vnd.google.note(保存便笺记录的目录)时,可以查看可用的便笺(action为android.app.action.VIEW),或者让用户选择一个便笺并返回给调用者(action为 android.app.action.PICK)。

3、第三个是,当type为vnd.android.cursor.item/vnd.google.note时,返回给调用者一个用户选择的便笺(action为android.app.action.GET_CONTENT),而用户却不需要知道便笺从哪里读取的。有了这些功能,下面的Intent就会被解析到NotesList这个activity:

复制内容到剪贴板

代码:

{ action=android.app.action.MAIN }:与此Intent匹配的Activity,将会被当作进入应用的顶级入口。

{ action=android.app.action.MAIN, category=android.app.category.LAUNCHER }:这是目前Launcher实际使用的 Intent,用于生成Launcher的顶级列表。

{ action=android.app.action.VIEW data=content://com.google.provider.NotePad/notes }:显示"content://com.google.provider.NotePad/notes"下的所有便笺的列表,使用者可以遍历列表,并且察看某便笺的详细信息。

{ action=android.app.action.PICK data=content://com.google.provider.NotePad/notes }:显示"content://com.google.provider.NotePad/notes"下的便笺列表,让用户可以在列表中选择一个,然后将选择的便笺的 URL返回给调用者。

{ action=android.app.action.GET_CONTENT type=vnd.android.cursor.item/vnd.google.note }:和上面的action为pick的Intent类似,不同的是这个Intent允许调用者(在这里指要调用NotesList的某个Activity)指定它们需要返回的数据类型,系统会根据这个数据类型查找合适的 Activity(在这里系统

会找到NotesList这个Activity),供用户选择便笺。

第二个Activity是com.google.android.notepad.NoteEditor,它为用户显示一条便笺,并且允许 用户修改这个便笺。

它定义了两个intent-filter,所以具有两个功能。

第一个功能是,当数据类型为 vnd.android.cursor.item/vnd.google.note时,允许用户查看和修改一个便签(action为 android.app.action.VIEW和android.app.action.EDIT)。

第二个功能是,当数据类型为 vnd.android.cursor.dir/vnd.google.note,为调用者显示一个新建便笺的界面,并将新建的便笺插入到便笺列表中(action为android.app.action.INSERT)。

有了这两个功能,下面的Intent就会被解析到NoteEditor这个activity:

复制内容到剪贴板

代码:

{ action=android.app.action.VIEW data=content://com.google.provider.NotePad/notes/{ID}} :向用户显示标识为 ID的便笺。

{ action=android.app.action.EDIT data=content://com.google.provider.NotePad/notes/{ID}}:允许用户编辑标识为ID的便笺。

{ action=android.app.action.INSERT data=content://com.google.provider.NotePad/notes }:在“content://com.google.provider.NotePad/notes”这个便笺列表中创建一个新的空便笺,并允许用 户编辑这个便签。当用户保存这个便笺后,这个新便笺的URI将会返回给调用者。

最后一个Activity是com.google.android.notepad.TitleEditor,它允许用户编辑便笺的标题。

它可以被实现为一个应用可以直接调用(在Intent中明确设置component属性)的类,不过这里我们将为你提供一个在现有的数据上发布可选操作的方法。

在这个 Activity的唯一的intent-filter中,拥有一个私有的action: com.google.android.notepad.action.EDIT_TITLE,表明允许用户编辑便笺的标题。

和前面的view和edit 动作一样,调用这个Intent 的时候,也必须指定具体的便笺(type为vnd.android.cursor.item/vnd.google.note)。不同的是,这里显示和编辑的只是便笺数据中的标题。

除了支持缺省类别(android.intent.category.DEFAULT),标题编辑器还支持另外两个标准类别: android.intent.category.ALTERNATIVE和

android.intent.category.SELECTED_ALTERNATIVE。

实现了这两个类别之后,其它 Activity就可以调用queryIntentActivityOptions(ComponentName, Intent[], Intent, int)查询这个Activity提供的action,而不需要了解它的具体实现;

或者调用addIntentOptions(int, int, ComponentName, Intent[], Intent, int, Menu.Item[])建立动态菜单。需要说明的是,在这个intent-filter中有一个明确的名称(通过android:label= "@string/resolve_title"指定),在用户浏览数据的时候,如果这个Activity是数据的一个可选操作,指定明确的名称可以为用户提供一个更好控制界面。

有了这个功能,下面的Intent就会被解析到TitleEditor这个Acti

vity:

复制内容到剪贴板

代码:

{ action=com.google.android.notepad.action.EDIT_TITLE data=content://com.google.provider.NotePad/notes/{ID}}:显示并且允许用户编辑标识为ID的便笺的标题。下载本文

显示全文
专题