从整体结构上来看,Intent 分为两种:显式的Intent 和隐式的Intent。区别在于,显式的Intent 指定了我要启动哪个Activity、Service或者BroadcastReceiver,但是隐式的Intent 却给定了限定条件,符合设定的一些action、data、category 等属性条件的都是我想要启动的对象。这个就好比电影【心花路放】里面的两个角色:黄徐峥饰演渤和徐峥,黄渤饰演的就属于显式的Intent,老子就要康小雨,除了她我谁都不爱;徐峥的角色就随(hao)意(se)多了,属于隐式的Intent,只要脸蛋好、身材辣(类似于action、data、category 等属性)的妹子,我都可以要。
在介绍两种Intent 之前,我们先来讲解下关于Intent 的六个属性:
一、基本属性
1)Component nameIntent 的Component 属性需要接受一个ComponentName 对象,ComponentName 包含如下几个构造方法:
构造方法 | 介绍 |
ComponentName(String pkg, String cls) | 创建pkg包下cls 类所对应的组件 |
ComponentName(Context pkg, String cls) | 创建pkg 所对应包下cls 类所对应的组件 |
ComponentName(Context pkg, Class<?> cls) | 创建pkg 所对应包下cls 类(泛型)所对应的组件 |
ComponentName(Parcel in) | 创建被序列化对象所对应的组件 |
除此之外,Intent 还包含了如下三个方法:
方法 | 介绍 |
setClass(Context packageContext, Class<?> cls) | 设置该Intent 将要启动组件对应的类 |
setClassName(Context packageContext, StringclassName) | 设置该Intent 将要启动packageContext 对应的类名 |
setClassName(String packageName, StringclassName) | 设置该Intent 将要启动包中对应的类名 |
2)Action
Action 属性是要完成指定的动作,比如
ACTION_VIEW
可以展现相应的组件显示给用户;
ACTION_SEND
则可以调用设备中的具备发送功能的app,如邮箱等。
系统给我们提供了一系列的Action,可以帮助我们完成一些常见的行为,如:
Action | 目标组件 | 介绍 |
ACTION_CALL | Activity | 初始化电话呼叫功能 |
ACTION_EDIT | Activity | 提供编辑功能 |
ACTION_MAIN | Activity | 作为程序的入口启动 |
...... | Activity | ...... |
ACTION_BATTERY_LOW | BroadcastReceiver | 电量低的警告 |
ACTION_HEADSET_PLUG | BroadcastReceiver | 耳机已经被插入或者拔出设备 |
...... | BroadcastReceiver | ...... |
这是因为,Android 系统只允许开发人员通过显式Intent 的方式直接启动Service(基于安全的角度考虑),否则的系统会抛出异常(自Android5.0 起)。
3)Data
关于Data 我们可以直接引用官方API 中的介绍说明:
数据运行的URI和其MIME类型,不同的action被配与不同的data说明。例如,如果是ACTION_EDIT,那么他的data就包含提供编辑功能的文本的URI。如果是ACTION_CALL,那么他的data就是号码的URI--tel:。同样的,如果是ACTION_VIEW并且data是http: URI,那么接收Intent的activity将下载并显示URI所指向的内容。
当为某个组件匹配一个可以处理数据的Intent的时候,通常除了要了解Data的URI以外,重要的是要知道Data的类型(MIME type)。例如,一个可以展示图片的组件不应该被调用来播放音频。
在很多情况下,Data的类型可以从URI中推测出来,特别是URI所展示的内容:指出了Data被用在什么位置及被哪种content provider控制(参考separate discussion on content providers)。但是Data的类型也可以在Intent中明确的设定。setData()方法设置Data的URI,setType()设置Data的类型(MIME type),setDataAndType()两者一起设置(注意:如果要同时设置Data和Type只能使用setDataAndType() 方法,如果先后使用了setData()和setType(),那么后者会将前者覆盖,达不到同时设置两者的目的)。
4)Category
Category 即种类、类别的意思,从它的单词中我们就可以看出它的作用,表示一种类型的组件来响应Action 中的行为(一般和Action 属性组合使用)。我们可以使用addCategory()方法往Intent 中添加属性,如果需要传入多种Category,那么继续调用此方法即可。
5)Extra
Intent 的Extra属性通常用于在多个Action 之间进行数据交换,Intent 的Extra 属性应该是一个Bundle 对象,Bundle 对象就像是一个Map 对象,它可以存入多个key-value 对,这样就可以通过Intent 在不同Activity 之间进行数据交换了。
6)Flag
Intent 的Flag 属性用于为该Intent 添加一些额外的标记,可以通知Android 系统决定如何启动Activity(如:此Activity 属于哪个任务)或者启动后需要做什么动作(比如,是否将此Activity 添加到Recent Activities 列表中),开发人员可调用 setFlags()
方法设置相应的标记。
二、显式Intent
系统根据Intent 接收到的参数,直接跳转到参数指定的组件(Activity、Service或者BroadcastRecevier)当中。下面代码是以显式的方式制定跳转到SubActivity 的例子:点击(此处)折叠或打开
- button = (Button) this.findViewById(R.id.button);
- button.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- Intent intent = new Intent();
- ComponentName component = new ComponentName(MainActivity.this, SubActivity.class);
- intent.setComponent(component);
- MainActivity.this.startActivity(intent);
- }
- });
点击(此处)折叠或打开
- button = (Button) this.findViewById(R.id.button);
- button.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- Intent intent = new Intent(MainActivity.this, SubActivity.class);
- MainActivity.this.startActivity(intent);
- }
- });
同样的,我们也可以使用相应的方法跳转到Service 和BroadcastReceiver,但是相应的
startActivity()
和
startActivityForResult()
方法就要换成Service 的
startService()
和
bindService()
方法,以及BroadcastReceiver 的
sendBroadcast()
、sendOrderedBroadcast()
和
sendStickyBroadcast()
方法。具体相关操作,请直接参照Service 和BroadcastReceiver 的API。
三、隐式Intent
在代码部分,开发人员可以按需给Intent 设置相应的属性,而在AndroidManifest.xml 中的组件也可以设置相应的【<intent-filter>......</intent-filter>】标签,当代码中的Intent 属性和xml 文件中组件的【<intent-filter>】标签相匹配的时候,就可以启动此标签所属的组件。当然,能够匹配的组件可能会有多个、一个甚至没有。所以,如果要启动的目标组件是Activity,在此之前可以通过Intent 对象调用resolveActivity(),当它返回的值非空时,那么开发人员就可以直接调用startActivity();而当返回的内容为空时,就不要调用startActivity() 方法了,以防App crash。下面是一个关于隐式Intent 的例子:
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
四、配置Intent Filter
<activity android:name="MainActivity">
<!-- This activity is the main entry, should appear in app launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- This activity handles "SEND" actions with text data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>