介绍
Intent的字面解释为“意图”。
众所周知,在Android中一个应用程序是由四大组件来协调完成工作的,而他们之间的通讯工作主要是通过Intent来完成的。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,可以将Intent理解为:不同组件之间通讯的“媒介”,专门提供组件之间互相调用的信息。
Intent启动组件的方法:
通过Intent启动Activity、Service、BroadCast的方法
组件名称 | 方法名称 | 方法解释 |
Activity | StartActivity() | 启动一个新的Activity,但不需要接收返回值 |
startActivityForResult() | 启动一个新的Activity,且可以接收目的Activity发送的返回值 |
Service | startService( ) | 请求启动给定的Service |
bindService( ) | 连接给定的Service,如果没有则需要创建 |
BroadCast | sendBroadcast() | 将Intent通过普通广播的形式发送出去 |
sendOrderedBroadcast() | 发送有序广播,广播接收器的优先级高,则能够先接收到广播,高级别的接收器可以拦截广播,也可以向广播中传入参数 |
sendStickyBroadcast() | 通过这种方式发送出去的广播会一直滞留(等待),以便接收器能够迅速接收到广播 |
Intent的属性
1、Component属性
要启动的组件名称,在创建Intent的时候是可选的,但是它是显式Intent的重要标志,有它就意味着只有Component name匹配上的那个组件才能接收你发送出来的显示intent。如果不写那么你创建的Intent就是隐式的,系统会根据这个intent的其他信息(比如:action、data、category)来确定哪些组件来接收这个intent,所以如果你想明确的启动哪个组件,就通过component name来指定。
Intent的Component属性需要接受一个ComponentName对象。创建一个Component对象需要指定包名和类名,可以唯一的确定一个组件类。这样应用程序可以根据给定的组件类去启动特定的组件。
Component的三种构造函数:
Component(String pkgName,String activityName);
//ComponentName componentName=new ComponentName("com.wyx.chapter_1","com.wyx.chapter_1.ThirdActivity");
Component(Context context, String activityName);
// ComponentName componentName=new ComponentName(this,"com.launchmodetest.SecondActivity");
Component(Context context,Class<?> cls);
//ComponentName componentName=new ComponentName(this,SecondActivity.class);
为Intent设置Component属性:
intent.setComponent(componentName);这样Intent就可以唯一确定所要启动的是哪一个组件。
Intent中也存在三个方法也能实现ComponentName的效果
Intent.
setClassName(String packageName, String className);
//intent.setClassName("com.wyx.chapter_1","com.wyx.chapter_1.ThirdActivity");
Intent.
setClassName(Context packageContext, String className);
//intent.setClassName(ThirdActivity.this,"com.launchmodetest.SecondActivity");
Intent.
setClass(Context packageContext, Class<?> cls);
//
intent.setClass(this,SecondActivity.class);
需要注意的一点是:在使用String来代表组件名称时一定要是
组件的全称,如
"com.wyx.chapter_1.ThirdActivity"。
2、Action属性
Action是指Intent要完成的动作,是一个字符串常量。
Android中提供了一些通用的Action,当然我们也可以自定义Action。
常用Action:
Action标示
|
含义
|
|
|
|
activity 作为Task中第一个Activity启动
|
|
broadcast receiver 电池电量过低警告.
|
|
broadcast receiver 屏幕变亮警告.
|
|
broadcast receiver 插拔耳机警告
|
3、Category属性
提供将要执行的action的额外信息,一般在隐式地启动activity时需要用到。
4、Data属性
通常用于向Action属性提供操作的数据。
该属性值为一个Uri对象。
Uri,全称
通用资源标志符(Universal Resource Identifier, 简称"URI")。Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。Uri字符串总满足这样的格式:scheme://host:port/path,比如某个图片资源的uri,
content://media/external/images/media/4。
Uri的结构中,scheme:URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效,即该URI无效。
host:URI的主机名,比如www.baidu.com,如果URI中没有指定scheme,那么整个URI的其他参数无效,即该URI无效。
port:URI中的端口号,比如80,当且仅当URI中指定了scheme和host参数,port才有效。
path:则表示Uri中所代表资源的完整路径。
5、Type属性
用于指定该Data所指定Uri对应的MIME类型,比如
image/png、
message/rfc822等。
Data属性通常与Type一起使用但关系比较微妙,在Java文件中为Intent设置Data属性与Type属性时,有以下三种情况:
1、如果为Intent先设置Data属性,后设置Type属性,则Type属性会将Data属性覆盖。
2、如果为Intent先设置Type属性,后设置Data属性,则Data属性会将Type属性覆盖。
3、如果希望Intent同时有Type属性和Data属性,则需要调用Intent的setDataAndType()方法。
public Intent setData(Uri data) {
mType = null;
//将Type置为null
在AndroidManifest文件中为组件声明Data和Type属性都通过<data .../>
<data
android:mimeType="" //用于声明该组件所能匹配的Intent的Type属性
android:scheme="" //
用于声明该组件所能匹配的Intent的Data属性的scheme部分
android:host=""
//
用于声明该组件所能匹配的Intent的Data属性的host部分
android:port=""
//
用于声明该组件所能匹配的Intent的Data属性的port部分
android:
path=""
//
用于声明该组件所能匹配的Intent的Data属性的path部分
android:pathPrefix=""
//
用于声明该组件所能匹配的Intent的Data属性的path部分前缀部分
android:pathPattern=""
//
用于声明该组件所能匹配的Intent的Data属性的path的字符串模板
/>
6、Extra属性
该属性通常用于在多个Activity之间进行数据传递。
调用Intent.putExtra()方法可以传入一个Bundle对象,
Bundle对象就像一个Map一样可以传入多组key-value,当然也可以不传Bundle,直接调用
putExtra(String name, String value)方法传一组key-value来传递数据。
7、Flag属性
该属性用于为Intent添加额外的控制旗标。
Intent寻找组件的方式:
1、显式Intent:
使用这种方式启动组件的前提是我们明确知道要启动哪一个组件,即知道组件的包名与组件名。
在此前提下,有三种方式设置所要启动的组件:
1、在创建Intent实例时为将目标组件作为Intent构造函数的参数传递给Intent。
2、调用Intent的setClass()方法或setClassName()方法,为Intent设置目标组件。
3、创建
componentName对象,为intent设置component属性。
2、隐式Intent:
没有指定Component属性,即使用Intent启动组件前,并不明确它到底要启动哪一个组件。这时虽然不明确具体要启动哪一个组件,但可以为Intent设置action、category、data等过滤条件,以此来筛选出要启动哪一个组价。
打个比方来说明这两种方式,把使用Intent来启动组件比作男生找女朋友。显式Intent就好比这个男生明确知道自己喜欢谁,所以他就会直接找那个女生表白,那个女生就相当于Android中的Component属性。而隐式Intent就比如那个男生并不确定自己喜欢谁,所以他找女朋友时,就会自己找女朋友的要求来找那个女生,而他的要求就比如女生要高、白、身材瘦一点等等。这些条件就相当于Android中的Action、category等。
IntentFilter匹配组件
在这里再说一下
IntentFilter,Intent Filter 描述了一个组件愿意接收什么样的 Intent 对象,Android 将其抽象为android.content.IntentFilter 类。在 Android 的 AndroidManifest.xml 配置文件中可以通过 <intent-filter >节点为一个 Activity 指定其 Intent Filter,以便告诉系统该 Activity 可以响应什么类型的 Intent。
当程序员使用 startActivity(intent) 来启动另外一个 Activity 时,如果直接指定 intent 了对象的 Component 属性,那么 Activity Manager 将试图启动其 Component 属性指定的 Activity。否则 Android 将通过 Intent 的其它属性从安装在系统中的所有 Activity 中查找与之最匹配的一个启动,如果没有找到合适的 Activity,应用程序会得到一个系统抛出的异常。这个匹配的过程如下:
一个组件中可以有多个intent-filter,一个Intent只要能够匹配任何一组
intent-filter即可成功启动对应的Activity。
Action的匹配规则:
1、 intent中的Action必须能够和intent-filter中的action匹配,这里指的匹配是两个action字符串必须完全一致。这里要注意一点一个intent-filter钟可能包含多个action,那么intent中的Action只要能够和intent-filter中的一个action相匹配即可匹配成功。
2、action区分大小写,大小写不同字符串相同则不能够匹配成功。
3、一个Intent中只能包含一个Action,如果先后设置了两个Action,则后面的Action会覆盖前面的Action。
4、使用隐式Intent启动组件时,Intent中必须包含一个Action。
category的匹配规则:
1、category在匹配的时候和action一样字符串完全一致。
2、区分大小写
3、一个Intent中可以包含多个category,但Intent中的category必须和
intent-filter的category都能够匹配成功才行。当然Intent中可以不必包含intent-filter中的所有category。
4、一个Intent中可以不包含category。但如果没有设置category,在启动组件时,会给Intent中默认添加一个
android.intent.category.DEFAULT的category,这也就是在AndroidManifest文件中为组件设置intent-filter时必须要有一个category标签,其值为android.intent.category.DEFAULT。