Intent是一个动作的完整描述,包含产生组件、接收组件和传递数据信息。并且,Intent利用消息实现应用程序之间的交互机制,这种信息描述了应用中一次操作的动作、数据以及附加数据。系统通过该Intent的描述负责找到对应的组件,并将Intent传递给调用的组件,完成组件的调用。
1.Intent属性
Intent由动作、数据、分类、类型、组件和扩展信息等内容组成,每个组成部分都由相应的属性进行表示,并提供设置和获取相应属性的方法。
组成 | 属性 | 设置属性方法 | 获取属性方法 |
动作 | Action | setAction() | getAction() |
数据 | Data | setData() | getData() |
分类 | Category | addCategory() | |
类型 | Type | setType() | getType() |
组件 | Component | setComponent() setClass() setClassName() | getComponent() |
扩展信息 | Extra | putExtra() | getXXXExtra()获取不同数据类型的数据,如int类型则使用getIntExtra(),字符串使用getStringExtra(),getExtras()获取Bundle包 |
(1)Action属性用于描述Intent要完成的动作,对要执行的动作进行简要的描述。Intent类定义了一系列Action属性常量,用来标识一套标准动作,如ACTION_CALL(打电话)、ACTION_EDIT(编辑)等。
(2)Data属性是执行动作的URI和MIME类型,Data属性常量如表3.
一般Action和Data匹配使用,不同的Action由不同的Data数据指定。
(3)Category属性指明一个执行Action的分类,Intent中定义了一系列Category属性常量,如表5.
(4)Component属性用于指明Intent目标组件的类名称。通常Android会根据Intent中包含的其他属性的信息,比如Action、Data/Type、Category进行查找,最终找到一个与之匹配的目标组件。但是,如果指定了Component这个属性,Intent则会直接根据组件名查找相应的组件,而不再执行上述查找过程。指定Component属性后,Intent的其他属性都是可选的。
(5)Extra属性用于添加一些附加信息,例如发送一个邮件,就可以通过Extra属性来添加主题(subject)和内容(body)。通过使用Intent对象的putExtra()方法来添加信息。将一个人的姓名附加到Intent对象中,代码如下。
Intent intent = new Intent();
intent.putExtra("name","zhangshan");
String name = intent.getStringExtra("name");//获取人名 zhangshan
2.Intent解析
根据Intent寻找目标组件时所采用的方式,可以将Intent分为两类:直接Intent和间接Intent。
- 直接Intent通过直接指定组件来实现,常用方法由setComponent()、setClassName()或setClass(),示例如下。
//创建一个Intent对象
Intent intent = new Intent();
//指定Intent对象的目标组件是Activity2
intent.setClass(Activity1.this,Activity2.class);
- 间接Intent通过Intent Filter过滤实现,过滤时通常根据Action、Data和Category属性进行匹配查找。Android提供两种生成Intent Filter的方式:一种是通过IntentFilter类生成;另一种通过在配置文件AdroidMainfest.xml中定义<intent-filter>元素生成。在AndroidMainfest.xml配置文件中,Intent Filter以<intent-filter>元素来指定。一个组件中可以有多个<intent-filter>元素,每个<intent-filter>元素描述不同的能力。示例如下。
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /><!--声明应用程序的入口--> <category android:name="android.intent.category.LAUNCHER" /><!--该活动优先级最高--> </intent-filter> </activity>
(1)<action>子元素
一个<intent-filter>中可以添加多个<action>子元素,实例如下。
<intent-filter>
<action android:value="android.intent.action.VIEW"/>
<action android:value="android.intent.action.EDIT"/>
<action android:value="android.intent.action.PICK"/>
...
</intent-filter>
<intent-filter>列表中的Action属性不能为空,否则所有的Intent都会因匹配失败而被阻塞。所以一个<intent-filter>元素下至少需要包含一个<action>子元素,这样系统才能处理Intent消息。
(2)<category>子元素
一个<intent-filter>中可以添加多个<category>子元素,示例如下。
<intent-filter>
<category android:value="android.intent.category.DEFAULT"/>
<category android:value="android.intent.category.BROWSABLE"/>
</intent-filter>
与Action一样,<intent-filter>列表中的Category属性不能为空。Category属性的默认值"android.intent.category.DEFAULT"是启动Activity的默认值,在添加其他Category属性值时,该值必须添加,否则会匹配失败。
(3)<data>子元素
一个<intent-filter>中可以包含多个<data>子元素,用于指定组件可以执行的数据,示例如下。
<intent-filter>
<data
android:mimeType="video/mpeg"<!--MIME类型,Intent对象和过滤器都可以用"*"匹配子类型字段,如“text/*”,“audio/*”表示任何子类型-->
android:scheme="http"
android:host="com.example.android"
android:path="folder/subfolder/1"
android:port="8888"/>
<data
android:mimeType="audio/mpeg"
android:scheme="http"<!--模式-->
android:host="com.example.android"<!--主机-->
android:path="folder/subfolder/2"
android:port="8888"/>
<data
android:mimeType="audio/mpeg"
android:scheme="http"
android:host="com.example.android"<!--路径-->
android:path="folder/subfolder/2"
android:port="8888"/><!--端口-->
</intent-filter>
3.Activity的跳转
在Android世界的Activity、BroadcastReceiver、Service、ContentProvider四大组件中,前三个都是通过Intent来解析并进行跳转的,intent可以说是连接这四大组件的重要桥梁。下面我们先介绍Intent是如何解析Activity跳转的。
一般情况下,一个Android应用程序需要多个屏幕,即多个Activity类,在这些Activity之间进行切换是通过Intent机制来实现的。在同一个应用程序中切换Activity时,可以通过直接Intent或是间接Intent进行多个Activity之间的跳转,使用的方法为startActivity(Intent intent),其中intent为添加的参数。
在使用Intent进行Activity之间的跳转时,我们通常有三种Intent跳转方式,即不带参数的跳转、带参数的跳转以及带返回值的跳转,下面我们来实现三种跳转方式
(1)不带参数跳转
Intent intent = new Intent();
intent.setClass(Activity1.this,Activity2.class);
startActivity(intent);
(2)带参数的跳转:用Bundle封装数据
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("Name","kate");
bundle.putString("Age","25");
intent.putExtras(bundle);
intent.setClass(Activity1.this,Activity2.class);
startActivity(intent);
Activity1跳转到Activity2之后,Activity2通过Bundle获取Intent穿过来的值,方法如下。
Bundle bundle = this.getIntent().getExtras();
String name = bundle.getString("name");
String age = bundle.getString("Age");
(3)带返回值的跳转
以下代码表示为第一个页面传送的参数值。
Intent intent = new Intent();
intent.setClass(Activity1.this,Activity2.class);
Bundle bundle = new Bundle();
bundle.putString("参数","参数值");
intent.putExtra(bundle);//注:不传参数的话,可以不加此行代码
this.startActivityForResult(intent,0);
注:startActivityForResult(Intent intent,Int requestCode)方法中的参数requestCode用于识别第二个页面传回来的值。
以下代码位于第二个页面返回方法中,即用setResult()准备好要回传的数据后,通过finish()方法结束该Activity,然后返回到Activity1中,通过Activity1中的onActivityResult()方法接收数据,如下图所示。
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("参数","参数值");
intent.putExtra(bundle);
intent.setClass(Activity2.this,Activity1.class);
setResult(RESLUT_OK,intent);//这里有两个参数(int resultCode,Intent intent)
finish();
注:对于setResult(int resultCode,Intent intent)的resultCode,如果Activity2子模块可能有几种不同的结果返回,可以用这个参数予以识别区分,比如这里的RESULT_OK值。
以下代码表示为第一个网页接收返回值,这里有三个参数requestCode、resultCode和data。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
//requestCode为Activity1的请求标识
//resultCode为回传的标记,在Activity2中使用的是RESULT_OK,所以在此处进行选择
case 0:
if(requestCode == RESULT_OK){
Bundle b = data.getExtras();//data为Activity2中回传的intent
String str = b.getString("参数");//str即为回传的值“参数值”
}
break;
default:
break;
}
}
此外,Intent的另外两种用途是:发送和接收广播、开启后台服务。
1)发送广播
//使用intent广播事件
//使用sendBroadcast 方法在组件直接匿名的广播消息
public static final String NEW_LIFEFORM_DETECTED = "com.paad.action.NEW_LIFEFORM";
Intent intent = new Intent(lifeformdetectedReceiver.NEW_LIFEFORM);
sendBroadcast(intent);
<!--使用Broadcast Receiver监听广播-->
<!--在代码中或者manifest中注册监听和广播的intent相符合的intent-filter-->
<!--在application节点中添加-->
<receiver android:name = ".lifeformdetectedreceiver" <!--要注册的broadcast的类名-->
<intent-filter>
<action android:name = "com.paad.alien.action.NEW.LIFEFORM" />
<intent-filter>
</receiver>
2)开启后台服务
Intent intent = new Intent();
intent.setClass(Activity.this,MyService.Class);
startService(intent);
3)锁定Activity的屏幕方向
<activity
android:name = "ClientActivity "
android:label="app name"
android:screenOrientation="portrait"><!--竖屏,值为landscape时为横屏-->
...
</activity>
4)全屏的Activity
在onCreate()方法中添加如下代码
getWindow.setFlags(WindowManger.LayoutParams.FLAG_FULLSCREEN,WindowManger.LayoutParams.FLAG_FULLSCREEN);//去除标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);