您的位置:首页 > 移动开发 > Android开发

Android Intent 详解

2009-12-22 09:49 441 查看

一、Intent作用

Intent是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯。比如说调用startActivity()来启动一个activity,或者由broadcaseIntent()来传递给所有感兴趣的BroadcaseReceiver,再或者由startService()/bindservice()来启动一个后台的service.所以可以看出来,intent主要是用来启动其他的activity或者service,所以可以将intent理解成activity之间的粘合剂。

二、Intent的构成

要在不同的activity之间传递数据,就要在intent中包含相应的东西,一般来说数据中最基本的应该包括:
<!--[if!supportLists]-->-<!--[endif]-->Action用来指明要实施的动作是什么,比如说ACTION_VIEW,ACTION_EDIT等。具体的可以查阅androidSDK->reference中的Android.content.intent类,里面的constants中定义了所有的action。
<!--[if!supportLists]-->-<!--[endif]-->Data要事实的具体的数据,一般由一个Uri变量来表示
下面是一些简单的例子:
ACTION_VIEW content://contacts/1 //显示identifier为1的联系人的信息。
ACTION_DIALcontent://contacts/1 //给这个联系人打电话

除了Action和data这两个最基本的元素外,intent还包括一些其他的元素,
<!--[if!supportLists]-->-<!--[endif]-->Category
(类别
:这个选项指定了将要执行的这个action的其他一些额外的信息,
例如
LAUNCHER_CATEGORY
表示
Intent
的接受者应该在
Launcher
中作为顶级应用出现;而
ALTERNATIVE_CATEGORY
表示当前的
Intent
是一系列的可选动作中的一个,这些动作可以在同一块数据上执行
具体同样可以参考androidSDK->reference中的Android.content.intent类。以前我也写过一篇于category有关的文章,点击这里可以查看。

<!--[if!supportLists]-->
-
<!--[endif]-->Type
(数据类型
):
显式指定
Intent
的数据类型(
MIME
)。一般
Intent
的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导


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


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


下面是这些额外属性的几个例子:
ACTION_MAINwithcategoryCATEGORY_HOME//用来Launchhomescreen.以前我也写过一篇于与之有关的文章,点击这里可以看到。

ACTION_GET_CONTENTwithMIMEtypevnd.android.cursor.item/phone//用来列出列表中的所有人的电话号码
综上可以看出,action、data/type、category和extras一起形成了一种语言,这种语言可以是android可以表达出诸如“给张三打电话”之类的短语组合。

三、intent的解析

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

<!--[if!supportLists]-->-<!--[endif]-->直接Intent:指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context,Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。
<!--[if!supportLists]-->-<!--[endif]-->间接Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。
对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有<intent-filter>及其中定义的Intent,通过PackageManager(注:PackageManager能够得到当前设备上所安装的applicationpackage的信息)来查找能过处理这个Intent的component。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的,判断方法如下:

<!--[if!supportLists]-->-<!--[endif]-->如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配;
<!--[if!supportLists]-->-<!--[endif]-->如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。
<!--[if!supportLists]-->-<!--[endif]-->如果Intent中的数据不是content:类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme(比如http:或者mailto:)进行匹配。同上,Intent的scheme必须出现在目标组件的scheme列表中。
<!--[if!supportLists]-->-<!--[endif]-->如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

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

<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.notepad">
<applicationandroid:icon="@drawable/app_notes"
android:label="@string/app_name">
<providerclass="NotePadProvider"
android:authorities="com.google.provider.NotePad"/>
<activityclass=".NotesList"="@string/title_notes_list">
<intent-filter>
<actionandroid:value="android.intent.action.MAIN"/>
<categoryandroid:value="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<actionandroid:value="android.intent.action.VIEW"/>
<actionandroid:value="android.intent.action.EDIT"/>
<actionandroid:value="android.intent.action.PICK"/>
<categoryandroid:value="android.intent.category.DEFAULT"/>
<typeandroid:value="vnd.android.cursor.dir/vnd.google.note"/>
</intent-filter>
<intent-filter>
<actionandroid:value="android.intent.action.GET_CONTENT"/>
<categoryandroid:value="android.intent.category.DEFAULT"/>
<typeandroid:value="vnd.android.cursor.item/vnd.google.note"/>
</intent-filter>
</activity>
<activityclass=".NoteEditor"="@string/title_note">
<intent-filterandroid:label="@string/resolve_edit">
<actionandroid:value="android.intent.action.VIEW"/>
<actionandroid:value="android.intent.action.EDIT"/>
<categoryandroid:value="android.intent.category.DEFAULT"/>
<typeandroid:value="vnd.android.cursor.item/vnd.google.note"/>
</intent-filter>
<intent-filter>
<actionandroid:value="android.intent.action.INSERT"/>
<categoryandroid:value="android.intent.category.DEFAULT"/>
<typeandroid:value="vnd.android.cursor.dir/vnd.google.note"/>
</intent-filter>
</activity>
<activityclass=".TitleEditor"="@string/title_edit_title"
android:theme="@android:style/Theme.Dialog">
<intent-filterandroid:label="@string/resolve_title">
<actionandroid:value="com.google.android.notepad.action.EDIT_TITLE"/>
<categoryandroid:value="android.intent.category.DEFAULT"/>
<categoryandroid:value="android.intent.category.ALTERNATIVE"/>
<categoryandroid:value="android.intent.category.SELECTED_ALTERNATIVE"/>
<typeandroid:value="vnd.android.cursor.item/vnd.google.note"/>
</intent-filter>
</activity>
</application>
</manifest>

例子中的第一个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.VIEWdata=content://com.google.provider.NotePad/notes}:显示"content://com.google.provider.NotePad/notes"下的所有便笺的列表,使用者可以遍历列表,并且察看某便笺的详细信息。

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

{action=android.app.action.GET_CONTENTtype=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.VIEWdata=content://com.google.provider.NotePad/notes/{ID}}:向用户显示标识为ID的便笺。

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

{action=android.app.action.INSERTdata=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这个Activity:

{action=com.google.android.notepad.action.EDIT_TITLEdata=content://com.google.provider.NotePad/notes/{ID}}:显示并且允许用户编辑标识为ID的便笺的标题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: