详解Android Intent

一、 Intent 作用

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

二、 Intent的构成

       要在不同的activity之间传递数据,就要在intent中包含相应的东西,一般来说数据中最基本的应该包括:

-          Action 用来指明要实施的动作是什么,比如说ACTION_VIEW, ACTION_EDIT等。具体的可以查阅android SDK-> reference中的Android.content.intent类,里面的constants中定义了所有的action。

 

标准的Activity Actions
ACTION_MAIN                               作为一个主要的进入口,而并不期望去接受数据
ACTION_VIEW                              向用户去显示数据
ACTION_ATTACH_DATA                  别用于指定一些数据应该附属于一些其他的地方,例如,图片数据应该附属于联系人
ACTION_EDIT                                访问已给的数据,提供明确的可编辑
ACTION_PICK                                从数据中选择一个子项目,并返回你所选中的项目
ACTION_CHOOSER                        显示一个activity选择器,允许用户在进程之前选择他们想要的
ACTION_GET_CONTENT                 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
ACTION_DIAL                                拨打一个指定的号码,显示一个带有号码的用户界面,允许用户去启动呼叫
ACTION_CALL                                根据指定的数据执行一次呼叫
(ACTION_CALL在应用中启动一次呼叫有缺陷,多数应用ACTION_DIAL,ACTION_CALL不能用在紧急呼叫上,紧急呼叫可以用ACTION_DIAL来实现)
ACTION_SEND                               传递数据,被传送的数据没有指定,接收的action请求用户发数据
ACTION_SENDTO                           发送一跳信息到指定的某人
ACTION_ANSWER                          处理一个打进电话呼叫
ACTION_INSERT                            插入一条空项目到已给的容器
ACTION_DELETE                           从容器中删除已给的数据
ACTION_RUN                                运行数据,无论怎么
ACTION_SYNC                              同步执行一个数据
ACTION_PICK_ACTIVITY               为已知的Intent选择一个Activity,返回别选中的类
ACTION_SEARCH                         执行一次搜索
ACTION_WEB_SEARCH                执行一次web搜索
ACTION_FACTORY_TEST              工场测试的主要进入点,


标准的广播Actions
ACTION_TIME_TICK                   当前时间改变,每分钟都发送,不能通过组件声明来接收,只有通过Context.registerReceiver()方法来注册
ACTION_TIME_CHANGED            时间被设置
ACTION_TIMEZONE_CHANGED   时间区改变
ACTION_BOOT_COMPLETED       系统完成启动后,一次广播
ACTION_PACKAGE_ADDED         一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
ACTION_PACKAGE_CHANGED    一个已存在的应用程序包已经改变,包括包名
ACTION_PACKAGE_REMOVED   一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
ACTION_PACKAGE_RESTARTED 用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
ACTION_PACKAGE_DATA_CLEARED 用户已经清楚一个包的数据,包括包名(清除包程序不能接收到这个广播)
ACTION_BATTERY_CHANGED 电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过Context.registerReceiver()注册
ACTION_UID_REMOVED 一个用户ID已经从系统中移除

 


-          Data 要事实的具体的数据,一般由一个Uri变量来表示

下面是一些简单的例子:

ACTION_VIEW content://contacts/1 //显示identifier为1的联系人的信息。
ACTION_DIAL  content://contacts/1 //给这个联系人打电话

除了Action和data这两个最基本的元素外,intent还包括一些其他的元素,

-          Category(类别): 这个选项指定了将要执行的这个action的其他一些额外的信息,例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这 些动作可以在同一块数据上执行。具体同样可以参考android SDK-> reference中的Android.content.intent类。以前我也写过一篇于category有关的文章,点击这里可以查看。

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

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

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

下面是这些额外属性的几个例子:

ACTION_MAIN with category CATEGORY_HOME //用来 Launch home screen. 以前我也写过一篇于与之有关的文章, 点击这里可以看到。
ACTION_GET_CONTENT with MIME type vnd.android.cursor.item/phone //用来列出列表中的所有人的电话号码

综上可以看出,action、 data/type、category和extras 一起形成了一种语言,这种语言可以是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中的所有<intent-filter>及其中定义的Intent,通过 PackageManager(注:PackageManager能够得到当前设备上所安装的application package的信息) 来查找能过处理这个Intent的component。在这个解析过程中,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如何定义及如何被解析。这个应用可以让用户浏览便笺列表、查看每一个便笺的详细信息。

Manifest.xml

Xml代码
  1. < manifest   xmlns:android = "http://schemas.android.com/apk/res/android"    
  2. package = "com.google.android.notepad" >    
  3.     < application   android:icon = "@drawable/app_notes"    
  4. android:label = "@string/app_name" >    
  5.     < provider   class = "NotePadProvider"    
  6. android:authorities = "com.google.provider.NotePad"   />    
  7.     < activity   class = ".NotesList" ="@string/title_notes_list" >    
  8.       < intent-filter >    
  9.         < action   android:value = "android.intent.action.MAIN" />    
  10.         < category   android:value = "android.intent.category.LAUNCHER"   />    
  11.       </ intent-filter >    
  12.       < intent-filter >    
  13.         < action   android:value = "android.intent.action.VIEW" />    
  14.         < action   android:value = "android.intent.action.EDIT" />    
  15.         < action   android:value = "android.intent.action.PICK" />    
  16.         < category   android:value = "android.intent.category.DEFAULT"   />    
  17.         < type   android:value = "vnd.android.cursor.dir/vnd.google.note"   />    
  18.       </ intent-filter >    
  19.       < intent-filter >    
  20.         < action   android:value = "android.intent.action.GET_CONTENT"   />    
  21.         < category   android:value = "android.intent.category.DEFAULT"   />    
  22.         < type   android:value = "vnd.android.cursor.item/vnd.google.note"   />    
  23.       </ intent-filter >    
  24.     </ activity >    
  25.     < activity   class = ".NoteEditor" ="@string/title_note" >    
  26.       < intent-filter   android:label = "@string/resolve_edit" >    
  27.         < action   android:value = "android.intent.action.VIEW" />    
  28.         < action   android:value = "android.intent.action.EDIT" />    
  29.         < category   android:value = "android.intent.category.DEFAULT"   />    
  30.         < type   android:value = "vnd.android.cursor.item/vnd.google.note"   />    
  31.       </ intent-filter >    
  32.       < intent-filter >    
  33.         < action   android:value = "android.intent.action.INSERT" />    
  34.         < category   android:value = "android.intent.category.DEFAULT"   />    
  35.         < type   android:value = "vnd.android.cursor.dir/vnd.google.note"   />    
  36.       </ intent-filter >    
  37.     </ activity >    
  38.     < activity   class = ".TitleEditor" ="@string/title_edit_title"   
  39. android:theme = "@android:style/Theme.Dialog" >    
  40.       < intent-filter   android:label = "@string/resolve_title" >    
  41.         < action   android:value = "com.google.android.notepad.action.EDIT_TITLE" />    
  42.         < category   android:value = "android.intent.category.DEFAULT"   />    
  43.         < category   android:value = "android.intent.category.ALTERNATIVE"   />    
  44.         < category   android:value = "android.intent.category.SELECTED_ALTERNATIVE" />    
  45.         < type   android:value = "vnd.android.cursor.item/vnd.google.note"   />    
  46.       </ intent-filter >    
  47.     </ activity >    
  48. </ application >    
  49. </ 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.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这个Activity:

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

 

**************************************************************************

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值