Intent机制

  Android中提供了Intent机制来协助应用间的交互与通讯。Intent负责对应用中一次操作的动作以及附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。
  Intent不仅可用于应用程序之间,也可用于应用程序内部的ActivityService之间的交互。因此Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。SDK给出了Intent作用的表现形式:

  • 通过startActivityActivity.startActivityForResult启动一个Activity
  • 通过startService启动一个服务,或者通过bindService和后台服务交互。
  • 通过广播方法(比如sendBroadcastsendOrderedBroadcastsendStickyBroadcast)发给broadcast receivers

Intent属性的设置

Action

  SDK中定义了一些标准的动作,Action就是表示了要执行操作的字符串(比如查看或选择),其对应着Intent Filter中的action标签<action />。常见的Activity Action Intent常量如下:

常量名称 常量值 意义
ACTION_MAIN android.intent.action.MAIN 应用程序入口
ACTION_VIEW android.intent.action.VIEW 显示数据给用户
ACTION_ATTACH_DATA android.intent.action.ATTACH_DATA 指明附加信息给其他地方的一些数据
ACTION_EDIT android.intent.action.EDIT 显示可编辑的数据
ACTION_PICK android.intent.action.PICK 选择数据
ACTION_CHOOSER android.intent.action.CHOOSER 显示一个Activity选择器
ACTION_GET_CONTENT android.intent.action.GET_CONTENT 获得内容
ACTION_DIAL android.intent.action.GET_CONTENT 显示打电话面板
ACITON_CALL android.intent.action.DIAL 直接打电话
ACTION_SEND android.intent.action.SEND 直接发短信
ACTION_SENDTO android.intent.action.SENDTO 选择发短信
ACTION_ANSWER android.intent.action.ANSWER 应答电话
ACTION_INSERT android.intent.action.INSERT 插入数据
ACTION_DELETE android.intent.action.DELETE 删除数据
ACTION_RUN android.intent.action.RUN 运行数据
ACTION_SYNC android.intent.action.SYNC 同步数据
ACTION_PICK_ACTIVITY android.intent.action.PICK_ACTIVITY 选择Activity
ACTION_SEARCH android.intent.action.SEARCH 搜索
ACTION_WEB_SEARCH android.intent.action.WEB_SEARCH Web搜索
ACTION_FACTORY_TEST android.intent.action.FACTORY_TEST 工厂测试入口点

常见的BroadcastIntent Action常量如下:

常量名称 描述
ACTION_TIME_TICK 系统时间每过一分钟发出的广播
ACTION_TIME_CHANGED 系统时间通过设置发生了变化
ACTION_TIMEZONE_CHANGED 时区改变
ACTION_BOOT_COMPLETED 系统启动完毕
ACTION_PACKAGE_ADDED 新的应用程序apk包安装完毕
ACTION_PACKAGE_CHANGED 现有应用程序apk包改变
ACTION_PACKAGE_REMOVED 现有应用程序apk包被删除
ACTION_UID_REMOVED 用户id被删除

Data

  此处所说的Intent中的data指的是URI对象和数据的MIME类型,其对应着Intent Filter中的data标签<data />
  一个完整的URIschemehostportpath组成,格式是<scheme>://<host>:<port>/<path>,例如content://com.example.project:200/folder/subfolder/etcURI就像一个数据链接,组件可以根据此URI获得最终的数据来源。通常将URIaction结合使用,比如我们将action设置为ACTION_VIEW,应该提供将要被编辑修改的文档的URI
  当创建了一个Intent对象的时候,除了指定URI之外,指定数据的MIME类型也很重要。例如一个Activity能够显示图片,但是不能够播放视频,显示图片的URI和播放视频的URI可能很类似,为了不让Android误将一个含有视频URIIntent对象传递给一个只能显示图片的Activity,我们需要在该ActivityIntent Filter中指定MIME类型为图片(例如<data android:mimeType="image/*" ... />),并且还要给Intent对象设置对应的图片类型的MIME,这样Android就会基于URIMIME类型将Intent传递给符合条件的组件。有个特例,如果URI使用的是content:协议,那么这就说明URI所提供的数据将来自于本地设备,即数据由ContentProvider提供,这种情况下Android会根据URI自动推断出MIME类型,此种情况我们无需再自己指定MIME类型。
  IntentActionData属性匹配如下:

Action属性 Data属性 说明
ACTION_VIEW content://contacts/people/1 显示id1的联系人信息
ACTION_DIAL content://contacts/people/1 id1的联系人电话号码显示在拨号界面中
ACITON_VIEW tel:123 显示电话为123的联系人信息
ACTION_VIEW http://www.google.com 在浏览器中浏览该网站
ACTION_VIEW file://sdcard/mymusic.mp3 播放MP3
ACTION_VIEW geo:39.2456,116.3523 显示地图

type

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

category

  category包含了关于组件如何处理Intent的一些其他信息。例如LAUNCHER_CATEGORY表示Intent的接受者应该在Launcher中作为*应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。其他的category如下:

Constant Meaning
CATEGORY_BROWSABLE The target activity can be safely invoked by the browser to display data referenced by a link. For example, an image or an e-mail message.
CATEGORY_GADGET The activity can be embedded inside of another activity that hosts gadgets.
CATEGORY_HOME The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed.
CATEGORY_LAUNCHER The activity can be the initial activity of a task and is listed in the top-level application launcher.
CATEGORY_PREFERENCE The target activity is a preference panel.

component

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

extras

  extras(附加信息)是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如如果要执行发送电子邮件这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。有的Intent需要靠URI携带数据,有的Intent是靠extras携带数据信息。
  你可以通过调用Intent对象的各种重载的putExtra(key,value)方法向Intent中加入各种键值对形式的额外数据,也可以直接创建一个Bundle对象,向该Bundle对象传入很多键值对,然后通过调用Intent对象的putExtras(Bundle)方法将其这些键值对设置到Intent对象中。

显式和隐式Intent

  理解Intent的关键之一是理解清楚Intent的两种基本用法:一种是显式的Intent,即在构造Intent对象时就指定接收者;另一种是隐式的Intent,即Intent的发送者在构造Intent对象时,并不知道也不关心接收者是谁,有利于降低发送者和接收者之间的耦合。
  对于显式IntentAndroid不需要去做解析,因为目标组件已经很明确;Android需要解析的是那些隐式Intent,通过解析,将Intent映射给可以处理此IntentActivityIntentReceiverService
  显式的Intent:如果Intent中明确包含了要启动的组件的完整类名(包名及类名),那么这个Intent就是explict(显式的)。使用显式Intent最典型的情形是在你自己的App中启动一个组件,因为你自己肯定知道自己的要启动的组件的类名。比如,为了响应用户操作通过显式的Intent在你的App中启动一个Activity或启动一个Service下载文件。
  隐式的Intent:如果Intent没有包含要启动的组件的完整类名,那么这个Intent就是implict(隐式的)。虽然隐式的Intent没有指定要启动的组件的类名,但是一般情况下,隐式的Intent都要指定需要执行的action。通常情况下,隐式的Intent只用在当我们想在自己的App中通过Intent启动另一个App组件的时候,让另一个App组件接收并处理该Intent。例如你想在地图上给用户显示一个位置,但是你的App又不支持地图展示,这时你可以将位置信息放入到一个Intent中,然后给它指定相应的action,通过这样隐式的Intent请求其他的地图型的App(例如Google Map)来在地图中展示一个指定的位置。隐式的Intent也体现了Android的一种设计哲学:我自己的App无需包罗万象所有功能,可以通过与其他App组合起来,给用户提供很好的用户体验。而连接自己的App与其他App的纽带就是隐式Intent
  当创建了一个显式Intent去启动ActivityService的时候,系统会立即启动Intent中所指定的组件。
  当创建了一个隐式Intent去使用的时候,Android系统会将该隐式Intent所包含的信息与设备上其他所有Appmanifest文件中注册组件的Intent Filters进行对比过滤,从中找出满足能够接收处理该隐式IntentApp和对应的组件。如果有多个App中的某个组件都符合条件,那么Android会弹出一个对话框让用户选择需要启动哪个App

Intent Filter

  Intent FilterIntent过滤器,一个组件可以包含0个或多个Intent FilterIntent Filter是写在Appmanifest文件中的,其通过设置actionuri数据类型等指明了组件能够处理接收的Intent的类型。如果你给你的Activity设置了Intent Filter,那么这就使得其他的App有可能通过隐式Intent启动你的这个Activity。反之,如果你的Activity不包含任何Intent Filter,那么该Activity只能通过显式Intent启动。由于我们一般不会暴露出我们组件的完整类名,所以这种情况下,其他的App基本就不可能通过Intent启动我们的Activity了(因为它们不知道该Activity的完整类名),只能由我们自己的App通过显式Intent启动。

上一篇:Android 开机启动程序


下一篇:隐式Intent调用启动浏览器