Android笔记(七十四) 详解Intent

我们最常使用Intent来实现Activity之间的转跳,最近做一个app用到从系统搜索图片的功能,使用到了intent的 setType 方法和 setAction 方法,网上搜索一番,发现实现转跳只是Intent功能的九牛一毛,现在对Intent功能做一个总结,以作备忘。

我们经常使用如下方法实现一个转跳:

Intent intent = new Inent(MainActivity.this,SecondActivity.class);
startActivity(intent);

其实这种写法还可以写作

Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
startActivity(intent);

这种启动方式被称之为“显式意图”,因为它直接指定了意图目标

还有一种方式称之为“隐式意图”,我们不直接指定目标组件,而是通过设置Intent的各个属性来启动目标组件

Intent

Intent由 ComponentName 、 Action 、 Data 、 Category 、 Extra 、 Flag 六部分来组成,Intent通过调用 setXXX() 方法来设置其对应的属性,下面详细介绍各个属性

【ComponentName】

ComponentName 用于标识位移的应用程序组件,即指明了期望的Intent,这种对象的名称是由目标组件的包名,与期望的类名组合而成,在Intent传递过程中,组件名称是一个可选项。当指定它时,便是显式的Intent消息;而当不指定它时,Android系统会根据其他信息,以及IntentFilter的过滤条件来选择相应的组件。

【Action】

Action 实际上就是一个描述了Intent所出发动作名称的字符串,在Intent类中,已经定义好很多字符串常量来表示不同的Action,当然开发人员也可以自定义Action

常见的Action常量

ACTION_CALL——播出Data里封装的电话号码

ACTION_EDIT——打开Data里指定数据所对应的编辑程序

ACTION_VIEW——打开能够显示Data之中封装的数据的应用程序

ACTION_MAIN——声明程序入口,该Activity并不会接收任何数据,同时结束后也部会返回任何数据

ACTION_BOOT_COMPLETED——BraodcastReceiver Action常量,表明系统启动完毕

ACTION_TIME_CHANGED——BraodcastReceiver Action常量,表示系统时间通过设置而改变

更多可以查看 http://www.cnblogs.com/xs104/p/5111858.html

因为API的更新,部分名称会改变,但基本思路不变。

【Data】

Data 主要是对Intent消息中数据的封装,主要描述Intent的动作所操作到底数据的URI及类型。不同类型的 Action会有不同的Data封装,例如打电话的Intent会封装tel://格式的电话URI,而ACTION_VIEW的Intent中Data则会封装http://格式的URI,正确的Data封装对Intent匹配请求同样非常重要

【Category】

Category 是对目标组件类别信息的描述,同样为一个字符串对象,一个Intent中可以包含多个Category,与Category相关的方法有三个:

1.添加一个Category——addCategory

2.删除一个Category——removeCategory

3.得到一个Category——getCategory

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。

【Extra】

extra 中封装了一些额外附加的信息,这些信息以键值对的形式存在,Intent可以通过putExtras()和getExtras()方法来存储和获取Extra,Android系统同样定义了一些Extra常量

EXTRA_CC,邮件抄送人邮箱地址。

EXTRA_EMAIL,装有邮件发送地址的字符串数组。

EXTRA_SUBJECT,当使用ACTION_SEND动作时,描述要发送邮件的主题。

EXTRA_TEXT,当使用ACTION_SEND动作时,描述要发送文本的信息。

【Flags】

android中Intent的Flags有20多种,如下

FLAG_GRANT_READ_URI_PERMISSION
FLAG_GRANT_WRITE_URI_PERMISSION
FLAG_DEBUG_LOG_RESOLUTION
FLAG_FROM_BACKGROUND
FLAG_ACTIVITY_BROUGHT_TO_FRONT
FLAG_ACTIVITY_CLEAR_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
FLAG_ACTIVITY_FORWARD_RESULT
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
FLAG_ACTIVITY_MULTIPLE_TASK
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_NO_ANIMATION
FLAG_ACTIVITY_NO_HISTORY
FLAG_ACTIVITY_NO_USER_ACTION
FLAG_ACTIVITY_PREVIOUS_IS_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_REORDER_TO_FRONT
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_TASK_ON_HOME
FLAG_RECEIVER_REGISTERED_ONLY

但是我们常用的只有4种

FLAG_ACTIVITY_CLEAR_TOP

例如现在的栈情况为:A B C D 。D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP 标记,则栈情况变为:A B。如果没有添加这个标记,则栈情况将会变成:A B C D B。也就是说,如果添加了FLAG_ACTIVITY_CLEAR_TOP 标记,并且目标Activity在栈中已经存在,则将会把位于该目标activity之上的activity从栈中弹出销毁。这跟上面把B的Launch mode设置成singleTask类似。
FLAG_ACTIVITY_NO_HISTORY
例如现在栈情况为:A B C。C通过intent跳转到D,这个intent添加FLAG_ACTIVITY_NO_HISTORY标志,则此时界面显示D的内容,如果此时D中又跳转到E,栈的情况变为:A B C E,此时按返回键会回到C,因为D根本就没有被压入栈中。
FLAG_ACTIVITY_SINGLE_TOP
和上面Activity的 Launch mode的singleTop类似。如果某个intent添加了这个标志,并且这个intent的目标activity就是栈顶的activity,那么 将不会新建一个实例压入栈中。

  

FLAG_ACTIVITY_NEW_TASK
例如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK 标 记,如果D这个Activity在Manifest.xml中的声明中添加了Task affinity,并且和栈1的affinity不同,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。如果D的Task affinity默认没有设置,或者和栈1的affinity相同,则会把其压入栈1,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK 标记效果是一样的了。 

  注意如果试图从非activity的非正常途径启动一个activity,比如从一个service中启动一个activity,则intent必须要添加 FLAG_ACTIVITY_NEW_TASK  标记。

  更多:Intent中的Flag

IntenFilter

IntentFilter 描述了一个组件愿意接收什么样的Intent对象,Android将其抽象为android.content.IntentFilter类。在 Android 的AndroidManifest.xml 配置文件中可以通过 <intent-filter> 节点,为一个Activity指定其IntentFilter,以便告诉系统该Activity可以响应什么类型的 Intent。这样的Intent称为隐式的Intent。

当程序员使用startActivity(intent)来启动另外一个Activity时,如果直接指定intent了对象的Component属性,那么Activity Manager将试图启动其Component属性指定的Activity。否则Android将通过Intent的其它属性,从安装在系统中的所有Activity中查找与之最匹配的一个启动。如果没有找到合适的Activity,应用程序会得到一个系统抛出的异常。

Intent的匹配

  Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的,判断方法如下:

  1 如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配;

  2 如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。

  3 如果Intent中的数据不是content: 类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme (比如 http: 或者mailto:) 进行匹配。

  同上,Intent 的scheme必须出现在目标组件的scheme列表中。

  4 如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。

  比如Intent中包含了两个类别:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。每一个通过startActivity()方法发出的隐式Intent都至少有一个category,就是"android.intent.category.DEFAULT",

所以只要是想接收一个隐式Intent的Activity都应该包括"android.intent.category.DEFAULT" category,不然将导致 Intent 匹配失败。

上一篇:葡萄城报表介绍:Web 报表


下一篇:Activity的加载模式及Intent.setFlags