Intent主要用来启动其他的Activity、Service、Broadcast
显示Intent与隐式Intent
Intent intent = new Intent();
intent.setClass(Context packageContext, OtherActivity.class); //显式intent,指明确指出此intent是启动哪个activity.
startActivity(intent);
<span style="background-color: rgb(255, 255, 255);">Intent intent = new Intent();
intent.setAction(Intent.ACTION_NEW); //隐式intent是指并没有指出要启动哪个activity,而要系统自动去判断并启动匹配的activity
startActivity(intent);</span>
显式Intent
有两种方式来显示的指示要启动的Activity:
方式一:(通过setClassName)
Intent intent = new Intent();
//表示希望启动com.example.test_permission包中的com.example.test_permission.MainActivity
intent.setClassName("com.example.test_permission", "com.example.test_permission.MainActivity");
startActivity(intent);
方式二:(通过SetClass)
Intent intent = new Intent();
intent.setClass(Context packageContext, OtherActivity.class);
startActivity(intent);
注意:Context代表访问该应用环境信息的接口,而包名是应用的唯一标识,所以它们有一一对应的关系。
隐式intent
public class Intent implements Parcelable, Cloneable { //... private String mAction;
private Uri mData;
private String mType;
private String mPackage;
private ComponentName mComponent;
private int mFlags;
private HashSet<String> mCategories;
private Bundle mExtras;
private Rect mSourceBounds;
从上面源码可以看出,Intent对象包含Data、Type、Component、Flag、Category、Action、Extra
Action、Category
<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的intent-filter的子元素代表了该Activity所能响应的Intent,一旦匹配就可以激活该Activity。
3.intent-filter代表了该组件所能满足的要求,只要能满足的要求大于等于intent的要求,就可以启动
Action:该activity可以执行的一个“抽象”动作
该标识用来说明这个activity可以执行哪些动作,所以当隐式intent传递过来action时,如果跟这里<intent-filter>所列出的任意一个匹配的话,就说明这个activity是可以完成这个intent的意图的,可以将它激活
ACTION_CALL activity 启动一个电话.
ACTION_EDIT activity 显示用户编辑的数据.
<span style="color:#ff0000;">ACTION_MAIN</span> activity 作为Task中第一个Activity启动,即应用程序入口
ACTION_SYNC activity 同步手机与数据服务器上的数据.
ACTION_BATTERY_LOW broadcastreceiver 电池电量过低警告.
ACTION_HEADSET_PLUG broadcastreceiver 插拔耳机警告
ACTION_SCREEN_ON broadcastreceiver 屏幕变亮警告.
<span style="color:#ff0000;">ACTION_VIEW</span> Activity 查看指定数据
Category:指定当前动作(Action)被执行的环境,为Action增加额外的附加类别信息
即这个activity在哪个环境中才能被激活。不属于这个环境的,不能被激活。
常用category: <span style="color:#ff0000;">CATEGORY_DEFAULT</span>:Android系统中默认的执行方式,按照普通Activity的执行方式执行。表示所有intent都可以激活它
CATEGORY_HOME:设置该组件为Home Activity。
CATEGORY_PREFERENCE:设置该组件为Preference。
<span style="color:#ff0000;">CATEGORY_LAUNCHER</span>:设置该组件为在当前应用程序启动器中优先级最高的Activity,通常与入口ACTION_MAIN配合使用。
CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。表示该activity只能用来浏览网页。
CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
Intent intent=new Intent();
intent.setAction(Intent.<span style="color:#ff6600;">ACTION_MAIN</span>);
intent.addCategory(Intent.<span style="color:#ff6600;">CATEGORY_HOME</span>);
startActivity(intent);
注意:
如果该activity想要通过隐式intent方式激活,那么不能没有任何category设置,至少包含一个android.intent.category.DEFAULT,因为当Intent被创建时,默认Category属性值为Intent.CATEGORY_DEFAULT。
Data、Type
Data Action属性执行时要操作的数据
在目标<data/>标签中包含了以下几种子元素,他们定义了url的匹配规则:
- android:scheme 匹配url中的前缀,指定数据的协议部分,除了“http”、“https”、“tel”...之外,我们可以定义自己的前缀
- android:host 匹配url中的主机名部分,如“google.com”,如果定义为“*”则表示任意主机名
- android:port 匹配url中的端口
- android:path 匹配url中的路径
- android:mimeType Type属性,指定该Data属性所指定的Uri的数据类型(MIME类型),允许使用通配符,而且可以是自定义的MIME类型,只要符合abc/xyz的格式的字符串即可
<activity android:name=".TargetActivity">
<span style="white-space:pre"> </span><intent-filter>
<span style="white-space:pre"> </span><action android:name="com.scott.intent.action.TARGET"/>
<span style="white-space:pre"> </span><category android:name="android.intent.category.DEFAULT"/>
<span style="white-space:pre"> </span><data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>
<span style="white-space:pre"> </span></intent-filter>
</activity>
注意:
1.只有<data.../>标签中指定的内容和Intent中携带的Data完全一致时,当前活动才能被激活。如果其它条件都足以激活该Activity,但intent却没有传进来指定类型的Data时,就不能激活该activity。所以想要启动上面的Activity,除了设置action外还要设置Data
2.Data属性与Type属性会相互覆盖,后这设置的会覆盖先设置的,如果想要同时存在,则要用setDataandType()方法
例子:打开浏览器,访问一个网页,action和data结合使用
Intent intent=new Intent();
intent.setAction(Intent.<span style="color:#ff6600;">ACTION_VIEW</span>);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
Extras
这个参数不参与匹配activity,而仅作为额外数据传送到另一个activity中,接收的activity可以将其取出来。这些信息并不是激活这个activity所必须的。也就是说激活某个activity与否只上action、data、catagory有关,与extras无关。而extras用来传递附加信息,诸如用户名,用户密码什么的。可通过putXX()和getXX()方法存取信息;也可以通过创建Bundle对象,再通过putExtras()和getExtras()方法来存取。
putXXX()方法的本质仍然是通过Bundle实现: public Intent putExtra(String name, long value) {
if (mExtras == null) {
mExtras = new <span style="color:#ff0000;">Bundle()</span>;
}
mExtras.<span style="color:#ff0000;">putLong</span>(name, value);
return this;
}
而传递一个Bundle:
public Intent putExtra(String name, Bundle value) {
if (mExtras == null) {
mExtras = new <span style="color:#ff0000;">Bundle</span>();
}
mExtras.<span style="color:#ff0000;">putBundle</span>(name, value);
return this;
}
归根结底都是通过Bundle来实现数据封装。而Bundle则是通过Map的数据结构来存储数据。
关于Bundle则是实现了Parcelable接口的类,通过上面提到的HashMap和一个Parcel来存储数据。
Intent源码6700多行代码,但真正核心代码 就那么几百行,大部分都用来定义常量字符串了
先来看一下
- public class Intent implements Parcelable, Cloneable
没错,它还实现了cloneable接口,但平常我们很少会用到它,其实现方法为:
- /**
- * Copy constructor.
- */
- public Intent(Intent o) {
- this.mAction = o.mAction;
- this.mData = o.mData;
- this.mType = o.mType;
- this.mPackage = o.mPackage;
- this.mComponent = o.mComponent;
- this.mFlags = o.mFlags;
- if (o.mCategories != null) {
- this.mCategories = new HashSet<String>(o.mCategories);
- }
- if (o.mExtras != null) {
- this.mExtras = new Bundle(o.mExtras);
- }
- if (o.mSourceBounds != null) {
- this.mSourceBounds = new Rect(o.mSourceBounds);
- }
- if (o.mSelector != null) {
- this.mSelector = new Intent(o.mSelector);
- }
- if (o.mClipData != null) {
- this.mClipData = new ClipData(o.mClipData);
- }
- }
- @Override
- public Object clone() {
- return new