Android Basic Intent
本技术点学习指导说明
Android的基本设计理念是鼓励减少组件间的耦合,因此Android提供了Intent。Intent提供了一种通用的消息系统,它允许在你 的应用 程序与其他应用程序间传递Intent来执行动作和产生事件。使用Intent可以激活Android应用的三个核心组件:Activity、 Service&Broadcastreceiver。
Intent简介
Intent组件不是四大组件,但却是连接四大组件的媒介
Intent的中文意 思是“意图,意向”,在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动 作、动作涉及数据、附 加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。
Intent可以划分为显式Intent和隐式Intent。
- 显式Intent:调用Intent.setComponent()或Intent.setClass()方法明确指定了组件名的Intent为显示Intent。其明确指定了Intent应该传递给哪个组件。
- 隐式Intent:没有明确指定组件名的Intent为隐式Intent。Android系统会根据隐式Intent中设置的Action、Category、Data找到最合适的组件来处理这个Intent
Intent传输机制
Android的三个基本组件——Activity,Service和Broadcast Receiver——都是通过Intent机制激活的,不同类型的组件有不同的传递Intent方式:
- Activity:一个intent对象传递给Context.startActivity()或Activity.startActivityForRestult()去启动一个活动或使一个已存在的活动去做新的事情。
- Service:一个intent对象传递给Context.startService()去初始化一个service或传递一个新的 指令给正在运行的service或者将一个intent传递给Context.bindService()去建立调用组件和目标服务之间的连接。
- Broadcast Receiver:一个intent对象传递给任何广播方法 (如 Context.sendBroadcast(),Context.sendOrderedBroadcast(),Context.sendStickyBroadcast()), 都 将传递到所有感兴趣的广播接收者。 在每种情况下,Android系统查找合适的activity、 service、 broadcastreceivers来响应意图,如果有必要的话,初始化他们。这些消息系统之间没有重叠,即广播意图仅会传递给广播 接收者,而不会传递 活动或服务,反之亦然。
Intent的属性
- component(组件):目的组件
- action(动作):用来表现意图的行动
- category(类别):用来表现动作的类别
- data(数据):表示与动作要操纵的数据
- ype(数据类型):对于data范例的描写
- extras(扩展信息):扩展信息
- Flags(标志位):期望这个意图的运行模式
下面分别详细介绍一下Intent的属性:
1. Action:使用android:name特性来指定对响应的动作名。动作名必须是独一无二的字符串。SDk中定义了一些标准的动作,但也可以根据相应的Actvity自定义动作。Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的Activity 定义时,可以在其 <intent-filter >节点指定一个 Action列表用于标识 Activity 所能接受的“动作”。
SDK中定义了一些标准的Action常量如下表所示:
Constant |
Target component |
Action |
ACTION_CALL |
activity |
Initiate a phone call. |
ACTION_EDIT |
activity |
Display data for the user to edit. |
ACTION_MAIN |
activity |
Start up as the initial activity of a task, with no data input and no returned output. |
ACTION_SYNC |
activity |
Synchronize data on a server with data on the mobile device. |
ACTION_BATTERY_LOW |
broadcast receiver |
A warning that the battery is low. |
ACTION_HEADSET_PLUG |
broadcast receiver |
A headset has been plugged into the device, or unplugged from it. |
ACTION_SCREEN_ON |
broadcast receiver |
The screen has been turned on. |
ACTION_TIMEZONE_CHANGED |
broadcast receiver |
The setting for the time zone has changed. |
2. Category:被执行动作的附加信息。如:CATEGORY_HOME则表示回到Home界面。
SDK文档中关于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. |
Category属性也是作为<intent-filter>子元素来声明的,例如:
<intent-filter>
<action android:name="com.vince.intent.MY_ACTION"></action>
<category android:name="com.vince.intent.MY_CATEGORY"></category>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
Action和Category通常是放在一起的。注:如果没有指定的category,则必须使用默认的DEFAULT也就是说:只 有<action>和<category>中的内容同时能够匹配上Intent中指定的action和category时,这 个 活动才能响应Intent。
如果使用的是DEFAULT这种默认的category,在稍后调用startActivity()方法的时候会自动将这个 category添加到Intent中。
3. Data:也就是执行动作要操作的数据(URI和MIME类型),不同的Action有不同的Data数据指定。比如:ACTION_VIEW要显示的应用应该和URI匹配。
4. type:显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式 指定的类型而不再进行推导。Intent的Type属性显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判 定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。
如果Intent对象中既包含Uri又包含Type,那么,在<intent-filter>中也必须二者都包含才能通过测试。
Type属性用于明确指定Data属性的数据类型或MIME类型,但是通常来说,当Intent不指定Data属性时,Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,所以无需指定Type属性。
data和type属性一般只需要一个,通过setData方法会把type属性设置为null,相反设置setType方法会把data设置为null,如果想要两个属性同时设置,要使用Intent.setDataAndType()方法。
5. extras:是其它所有附加信息的集合,主要用于传递目标组件所需要的额外数据。附加信息可以使用putExtras()和getExtras()作为Bundle来读和写。
6. Flags:期望这个意图的运行模式,常用于Activity的场景中,和Activity的启动模式有着密切的关系。如Intent.FLAG_ACTIVITY_NEW_TASK,默认的跳转类型,它会重新创建一个新的Activity。
Android如何解析Intent
Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent, 最终找到匹配的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,解析得到的目标组件必须至少包含这两个类别。
IntentFilter
IntentFilter类表示Intent过滤器, 大部分情况下, 每一个component都会定义一个或多个IntentFilter,用于表明其可处理的Intent。
一般来说,component的IntentFilter应该在AndroidManifest.xml文件中定义。
定义的方法:
在<activity>,<receiver>, <service>元素中增加一个或多个<intent-filter>子元素。如:
<!-- 声明作为程序入口的Activity-->
<activityandroid:name=".FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
关于IntentFilter的几点注意事项:
(1).android.intent.action.MAIN 与 android.intent.category.LAUNCHER
android.intent.action.MAIN决定一个应用程序最先启动那个组件
android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里(说白了就是是否在桌面上显示一个图标)
这两个属性组合情况:
第一种情况:有MAIN,无LAUNCHER,程序列表中无图标
原因:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里
第二种情况:无MAIN,有LAUNCHER,程序列表中无图标
原因:android.intent.action.MAIN决定应用程序最先启动的Activity,如果没有Main,则不知启动哪个Activity,故也不会有图标出现
所以这两个属性一般成对出现。
如果一个应用中有两个组件intent-filter都添加了android.intent.action.MAIN和
android.intent.category.LAUNCHER这两个属性, 则这个应用将会显示两个图标, 写在前面的组件先运行。
(2).关于隐式intent
每一个通过 startActivity() 方法发出的隐式 Intent 都至少有一个 category,就是 "android.intent.category.DEFAULT",所以只要是想接收一个隐式 Intent 的 Activity 都应该包括 "android.intent.category.DEFAULT" category,不然将导致 Intent 匹配失败.
比如说一个activity组件要想被其他组件通过隐式intent调用, 则其在manifest.xml中的声明如下:
<activity android:name="com.gesture.QGestureListActivity">
<intent-filter>
<action android:name="com.google.test" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
(3).关于intent-filter匹配优先级
首先查看Intent的过滤器(intent-filter),按照以下优先关系查找:action->data->category
(4).android.intent.category.LAUNCHER与android.intent.category.HOME的区别
android.intent.category.LAUNCHER:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里,就是android开机后的主程序列表。
android.intent.category.HOME:按住“HOME”键,该程序显示在HOME列表里。