Intent对象携带了Android系统用来确定要启动哪个组件的信息(例如,准确的组件名称或应当接收该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主要由ComponentName、Action、Data、Category、Extra、Flag 六部分来组成,Intent通过调用setXXX()方法来设置其对应的属性,下面详细介绍各个属性。
public class MainActivity extends Activity {
private Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
ComponentName com = new ComponentName(MainActivity.this, SecondActivity.class);
intent.setComponent(com);
startActivity(intent);
}
});
}
}
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常量,表示系统时间通过设置而改变
public class MainActivity extends Activity {
private Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
Uri uri = Uri.parse("tel:10086");
intent.setAction(Intent.ACTION_CALL);
intent.setData(uri);
startActivity(intent);
}
});
}
}
Data
Data主要是对Intent消息中数据的封装,主要描述Intent的动作所操作到底数据的URI及类型。不同类型的 Action会有不同的Data封装,例如打电话的Intent会封装tel://格式的电话URI,而ACTION_VIEW的Intent中Data则会封装http:// 格式的URI,正确的Data封装对Intent匹配请求同样非常重要
Category
Category是对目标组件类别信息的描述,同样为一个字符串对象,一个Intent中可以包含多个Category,与Category相关的方法有三个:
添加一个Category——addCategory
删除一个Category——removeCategory
得到一个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。
public class MainActivity extends Activity {
private Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setAction("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
}
});
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intenttest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity" >
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.activitytest.MY_CATEGORY" />
</intent-filter>
</activity>
</application>
</manifest>
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多种,如下:
但是我们常用的只有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 标记。