在Android 帮助文档中,Intent的介绍为An intent is an abstract description of an operation to be performed,意思是一个Intent是对一个即将进行的操作的抽象,Intent的字面意识就是”意图”,Android应用程序中的三种其他应用程序基本组件——Activity, Service和Broadcast Receiver,都是使用称为intent的消息来”激活”的。对于向这三种组件发送intent有不同的机制:
使用Context.startActivity() 或 Activity.startActivityForResult(), 传入一个intent来启动一个Activity. 使用 Activity.setResult(), 传入一个intent来从Activity中返回结果.
将intent对象传给Context.startService()来启动一个Service或者传消息给一个运行的Service. 将intent对象传给 Context.bindService()来绑定一个Service.
将intent对象传给 Context.sendBroadcast(), Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等广播方法,则它们被传给 Broadcast Receiver.
在上述三种情况下, Android系统会自己找到合适的Activity, Service, 或者 Broadcast Receivers来响应Intent. 三者的Intent相互独立互不干扰.也许有人会问,比如说在Android中启动另一个Activity完全可以直接使用Context.startActivity(Class startClass)的方式来启动一个Activity,为什么还需要使用Intent,不有点”脱裤子放屁”——多此一举吗?其实这种方法虽然简单,去背离了Android设计的初衷,Android使用Intent封装程序的”调用意图”,不管是启动一个Activity或是一个Service或者是启动一个BroadcastReceiver,都可以使用统一的Intent这种”启动意图”,这样就使用了一致的编程模型,也是一种高层次的”解耦”。
1、Intent简介
Intent代表了Android应用的启动”意图”,Android应用将会根据Intent来启动指定组件,至于到底启动哪个组件,则取决于Intent的各个属性。下面就来介绍一下Intent的各种发展,以及Android如何根据不同属性来启动相应的组件。Intent是由Component、Action、Data、Category、Extra及Flag六部分组成的,接下来将分别对其进行详细介绍。
(1)组件名称
组件名称实际上就是一个ComponentName对象,用于标识唯一的应用程序组件,即指明了期望的Intent组件,这种对象的名称是由目标组件的类名与目标组件的包名组合而成的。在Intent传递过程中,组件名称是一个可选项,当指定它时,便是显式的Intent消息,我们称为“显示意图”,当不指定它时,Android系统则会根据其他信息及IntentFilter的过滤条件选择相应的组件,我们称之为 “隐式意图”。
//创建一个ComponentName对象
ComponentName componentName = new ComponentName(
IntentDemoActivity.this, SecondActivity.class);
Intent intent = new Intent();
//设置Intent的Component属性
intent.setComponent(componentName);
//启动SecondActivity
startActivity(intent);
上面的代码其实完全可以简化为:
Intent intent = new Intent(IntentDemoActivity.this, SecondActivity.class);
//启动SecondActivity
startActivity(intent);
(2)Action
Action实际上就是一个描述了Intent所触发动作名称的字符串,在Intent类中,已经定义好多字符串常量来表示不同的Action,当然,开发人员也可以自定义Action,其定义规则同样非常简单。动作名必须是独一无二的字符串,所以,一个好的习惯是使用基于Java包的命名方式的命名系统。
系统定义的Action常量有很多,下面只列出其中一些较常见的。
ACTION_CALL,拨出Data里封装的电话号码。
ACTION_EDIT,打开Data里指定数据所对应的编码程序。
ACTION_VIEW,打开能够显示Data中封装的数据的应用程序。
ACTION_MAIN,声明程序的入口,该Action并不会接收任何数据,同时结束后也不会返回任何数据。
ACTION_BOOT_COMPLETED,BroadcastReceiver Action的常量,表明系统启动完毕。
ACTION_TIME_CHANGED,BroadcastReceiver Action的常量,表示系统时间通过设置而改变。
//声明一个Intent对象
Intent intent = new Intent();
/**
* 设置Action属性,这里是跳到拨号界面
* ACTION_DIAL = "android.intent.action.DIAL";
*/
intent.setAction(Intent.ACTION_DIAL);
startActivity(intent);
Action很大程度上决定了Intent的另外部分的结构, 就像一个方法名决定了它接受的参数和返回值一样. 因此, 最好给Action一个最能反映其作用的名字.一个Intent对象中的Action是使用getAction()和setAction()来读写的.
(3)Data
Data主要是对Intent消息中数据的封装,主要描述Intent的动作所操作到的数据的URI及类型。不同类型的Action会有不同的Data封装,例如打电话的Intent会封装tel://格式的电话URI,而ACTION_VIEW的Intent中Data则会封装http:格式的URI。正确的Data封装对Intent匹配请求同样非常重要。
//声明一个Intent对象
Intent intent = new Intent();
/**
* 设置Action属性,这里是跳到拨号界面
* ACTION_DIAL = "android.intent.action.DIAL";
*/
intent.setAction(Intent.ACTION_DIAL);
Uri uri = Uri.parse("tel:0-123-456-789");
intent.setData(uri);
startActivity(intent);
(4)Category
Category是对目标组件类别信息的描述。同样作为一个字符串对象,一个Intent中可以包含多个Category。与Category相关的方法有三个,addCategory添加一个Category,removeCategory删除一个Category,而getCategories得到一个Category。Android系统同样定义了一组静态字符常量来表示Intent的不同类别,下面列出一些常见的Category常量。
CATEGORY_GADGET,表示目标Activity是可以嵌入到其他Activity中的。
CATEGORY_HOME,表明目标Activity为HOME Activity。
CATEGORY_TAB,表明目标Activity是TabActivity的一个标签下的Activity。
CATEGORY_LAUNCHER,表明目标Activity是应用程序中最先被执行的Activity。
CATEGORY_PREFERNCE,表明目标Activity是一个偏好设置的Activity。
一个Intent最多只能包含一个Action属性,但是一个Intent中可以包含多个Category属性。
(5)Extra
Extra中封装了一些额外的附加信息,这些信息是以键值对的形式存在的。Intent可以通过putExtras()与getExtras()方法来存储和获取Extra。在Android系统的Intent类中,同样对一些常用的Extra键值进行了定义,如下所示。
EXTRA_BCC,装有邮件密送地址的字符串数组。
EXTRA_EMAIL,装有邮件发送地址的字符串数组。
EXTRA_UID,使用ACTION_UID_REMOVED动作时,描述删除用户的id。
EXTRA_TEXT,当使用ACTION_SEND动作时,描述要发送文本的信息。
(6)Flag
一些有关系统如何启动组件的标志位,Android同样对其进行了封装。
2.IntentFilter的简介
IntentFilter实际上相当于Intent的过滤器,一个应用程序开发完成后,需要告诉Android系统自己能够处理哪些隐形的Intent请求,这就需要声明IntentFilter。IntentFilter的使用方法实际上非常简单,仅声明该应用程序接收什么样的Intent请求即可。
IntentFilter过滤Intent时,一般是通过Action、Data及Category三方面进行监测的。接下来分别对这三方面进行介绍。
(1)检查Action
一个Intent只能设置一种Action,但是一个IntentFilter却可以设置多个Action过滤。当IntentFilter设置了多个Action时,只需一个满足即可完成Action验证。当IntentFilter中没有说明任何一个Action时,那么任何的Action都不会与之匹配。而如果Intent中没有包含任何Action,那么只要IntentFilter中含有Action时,便会匹配成功。
(2)检查Data
数据的监测主要包含两部分,即数据的URI及数据类型,而数据URI又被分成三部分进行匹配(scheme、authority、path),只有这些全部匹配时,Data的验证才会成功。
(3)检查Category
IntentFilter同样可以设置多个Category,当Intent中的Category与IntentFilter中的一个Category完全匹配时,便会通过Category的检查,而其他的Category并不受影响。但是当IntentFilter没有设置Category时,只能与没有设置Category的Intent相匹配。