码迷,mamicode.com
首页 > 其他好文 > 详细

Activity Intent详解

时间:2015-07-28 19:08:05      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

1、Intent简介

Intent代表了Android应用的启动“意图”,Android应用将会根据Intent来启动指定组件,至于到底启动哪个组件,则取决于Intent的各个属性。下面就来介绍一下Intent的各种发展,以及Android如何根据不同属性来启动相应的组件。Intent是由Component、Action、Data、Category、Extra及Flag六部分组成的,接下来将分别对其进行详细介绍。

(1)Component name

组件名称实际上就是一个ComponentName对象,用于标识唯一的应用程序组件,即指明了期望的Intent组件,这种对象的名称是由目标组件的类名与目标组件的包名组合而成的。在Intent传递过程中,组件名称是一个可选项,当指定它时,便是显式的Intent消息,我们称为“显示意图”,当不指定它时,Android系统则会根据其他信息及IntentFilter的过滤条件选择相应的组件,我们称之为“隐式意图”

(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

首先简单介绍下Task和Activity的关系:

Task就像一个容器,而Activity就相当与填充这个容器的东西,第一个东西(Activity)则会处于最下面,最后添加的东西(Activity)则会在最上面。从Task中取出东西(Activity)是从最顶端取出,也就是说最先取出的是最后添加的东西(Activity),以此类推,最后取出的是第一次添加的Activity,而Activity在Task中的顺序是可以控制的,在Activity跳转时用到Intent Flag可以设置新建activity的创建方式。

(1) 前提: Activity A和Activity B在同一个应用中. 

     操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B(堆栈状态: AB), 按下BACK返回键(堆栈状态: A). 

(2) 前提: Activity A和Activity B在同一个应用中, 应用名称为"TaskOne应用".

     操作: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),在Activity A中启动Activity B(TaskA堆栈状态: AB), 长按Home键, 返回Launcher, 启动其它应用(如:电子书),开僻一个新Task堆栈, 命名: TaskB, 长按Home健, 返回Launcher, 单击"TaskOne应用"图标, 此时TaskA堆栈返回前台,Activity B为栈顶应用, 供用户使用. 

(3) 前提: Activity A在名称为"TaskOne应用"的应用中, Activity C在名称为"TaskTwo应用"的应用中.

     操作: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),在Activity A中启动Activity C(TaskA堆栈状态: AC),长按Home键, 返回Launcher, 启动"TaskTwo应用"即Activity C,开僻新的Task堆栈, 命名为TaskB, 按BACK键返回Launcher, 单击"TaskOne应用"图标, 此时TaskA堆栈返回前台,Activity C为栈顶应用, 供用户使用. 

1.FLAG_ACTIVITY_NEW_TASK: 设置此状态,记住以下原则,首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,注意同一个应用程序中的activity的亲和性一样,所以下面的a情况会在同一个栈中,前面这句话有点拗口,请多读几遍),如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity。

a). 前提: Activity A和Activity B在同一个应用中。

操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B, 启动Activity B的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK, Activity B被压入Activity A所在堆栈(堆栈状态: AB)。

   原因: 默认情况下同一个应用中的所有Activity拥有相同的关系(taskAffinity).

b). 前提: Activity A在名称为"TaskOne应用"的应用中, Activity C和Activity D在名称为"TaskTwo应用"的应用中。

操作1: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),在Activity A中启动Activity C, 启动Activity C的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK,Android系统会为Activity C开僻一个新的Task, 命名为TaskB(TaskB堆栈状态: C), 长按Home键, 选择TaskA,Activity A回到前台, 再次启动Activity C(两种情况1.从桌面启动;2.从Activity A启动,两种情况一样), 这时TaskB回到前台, Activity C显示, 供用户使用, 即:包含FLAG_ACTIVITY_NEW_TASK的Intent启动Activity的Task正在运行, 则不会为该Activity创建新的Task,而是将原有的Task返回到前台显示。

操作2: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),在Activity A中启动Activity C,启动Activity C的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK,Android系统会为Activity C开僻一个新的Task, 命名为TaskB(TaskB堆栈状态: C),  在Activity C中启动Activity D(TaskB的状态: CD) 长按Home键, 选择TaskA, Activity A回到前台, 再次启动Activity C(从桌面或者ActivityA启动,也是一样的),这时TaskB回到前台, Activity D显示,供用户使用.说明了在此种情况下设置FLAG_ACTIVITY_NEW_TASK后,会先查找是不是有Activity C存在的栈,根据亲和性(taskAffinity),如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的顺序不变。

2.FLAG_ACTIVITY_CLEAR_TOP:

前提: Activity A, Activity B, Activity C和Activity D在同一个应用中.

操作: Activity A启动开僻Task堆栈(堆栈状态: A), 在Activity A中启动Activity B(堆栈状态: AB), 在Activity B中启动Activity C(堆栈状态: ABC), 在Activity C中启动Activity D(堆栈状态: ABCD), 在Activity D中启动Activity B,启动Activity B的Intent的Flag设置为FLAG_ACTIVITY_CLEAR_TOP, (堆栈状态: AB)。

3.FLAG_ACTIVITY_BROUGHT_TO_FRONT:

前提: Activity A在名称为"TaskOne应用"的应用中, Activity C和Activity D在名称为"TaskTwo应用"的应用中.

操作: 在Launcher中单击"TaskOne应用"图标, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),在Activity A中启动Activity C,启动Activity C的Intent的Flag设为FLAG_ACTIVITY_NEW_TASK,Android系统会为Activity C开僻一个新的Task, 命名为TaskB(TaskB堆栈状态: C), 在Activity C中启动Activity D(TaskB的堆栈状态: CD), 长按Home键, 选择TaskA, Activity A回到前台, 在Activity A中再次启动Activity C,在启动Activity C的Intent中设置Flag为FLAG_ACTIVITY_BROUGHT_TO_FRONT, TaskB回到前台,Activity C显示, (TaskB的堆栈状态: C)。

4.FLAG_ACTIVITY_MULTIPLE_TASK:

与FLAG_ACTIVITY_NEW_TASK结合使用, 首先在Intent中设置FLAG_ACTIVITY_NEW_TASK, 打开Activity,则启动一个新Task, 接着在Intent中设置FLAG_ACTIVITY_MULTIPLE_TASK, 再次打开同一个Activity,则还会新启动一个Task。

5.FLAG_ACTIVITY_SINGLE_TOP:

当前Task堆栈中存在ABCD四个Activity, A是栈顶Activity, D为栈底Activity, 存在打开A的Intent中设置了FLAG_ACTIVITY_SINGLE_TOP标志, 则会使用栈顶A, 而不会从新New A.

6.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:

一般与FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET结合使用,如果设置该属性,这个activity将在一个新的task中启动或者或者被带到一个已经存在的task的顶部,这时这个activity将会作为这个task的首个页面加载。将会导致与这个应用具有相同亲和力的task处于一个合适的状态(移动activity到这个task或者从中移出),或者简单的重置这个task到它的初始状态FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET:在当前的Task堆栈中设置一个还原点,当带有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的Intent请求启动这个堆栈时(典型的例子是用户从桌面再次启动这个应用),还原点之上包括这个应用将会被清除。应用场景:在email程序中预览图片时,会启动图片观览的actvity,当用户离开email处理其他事情,然后下次再次从home进入email时,我们呈现给用户的应该是上次email的会话,而不是图片观览,这样才不会给用户造成困惑。

例: 存在Activity A, Activity B, Activity C, Activity A启动开僻Task堆栈, 命名为TaskA(TaskA堆栈状态: A),在Activity A中启动Activity B(TaskA堆栈状态: AB), 接着Activity B启动Activity C(TaskA堆栈状态: ABC),启动Activity C的Intent中设置FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET标题, 这样TaskA中有一个还原点,当有包含FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的Intent请求TaskA堆栈时(比如请求Activity A),系统就会将还原点以上的Activity清除, TaskA堆栈中只剩下了AB。


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相匹配。

Activity Intent详解

标签:

原文地址:http://my.oschina.net/u/1175007/blog/484752

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!