Intent
用于启动
Activity,Service,
以及
BroadcastReceiver
三种组件
,
同时还是组件之间通信的重要媒介。
使用 Intent 启动组件的优势
1, Intent 为组件的启动提供了一致的编程模型。 无论想要启动的组件是 Activity,Service, 还是 BroadcastReceiver, 都可以使用 Intent 封装启动的意图。
2, 在某些时候 , 应用程序只是想启动具有某种特征的组件 , 并不想和某个特定的组件耦合。 使用 Intent 可以方便的达到这种高层次解耦的目的。
Intent 的 Component 属性
Intent 对象的 setComponent(ComponentNamecomp) 方法用于设置 Intent 的 Component 属性。 ComponentName 包含如下几个构造器 :
ComponentName(Stringpkg, String cls)
ComponentName(Contextpkg, String cls)
ComponentName(Contextpkg, Class<?> cls)
由以上的构造器可知 , 创建一个 ComponentName 对象需要指定包名和类名 -- 这就可以唯一确定一个组件类 , 这样应用程序即可根据给定的组件类去启动特定的组件。 例如 :
ComponentName comp =new ComponentName(FirstActivity 。 this,SecondActivity 。 class);
Intent intent = newIntent();
intent 。 setComponent(comp);
以上三句代码创建了一个 intent 对象 , 并为其指定了 Component 属性 , 完全等价于下面的代码 :
Intent intent = newIntent(FirstActivity 。 this,SecondActivity 。 class);
除了使用 setComponent() 之外 , 还可以使用 setClass(),setClassName() 来显式指定目标组件 , 还可以调用 getComponent() 方法获得 Intent 中封装的 ComponentName 对象。
当程序采用这种形式启动组件时 , 在 Intent 中明确的指定了待启动的组件类 , 此时的 Intent 属于显式 intent, 显式 Intent 应用场合比较狭窄 , 多用于启动本应用中的 component, 因为这种方式需要提前获知目标组件类的全限定名。 而隐式 Intent 则通过 Intent 中的 action,category, data 属性指定目标组件需要满足的若干条件 , 系统筛选出满足所有条件的 component, 从中选择最合适的 component 或者由用户选择一个 component 作为目标组件启动。
如果 Intent 中指定了 ComponentName 属性 , 则 Intent 的其他属性将被忽略。
Intent 的 Action 属性
action 属性是一个字符串 , 代表某一种特定的动作。 Intent 类预定义了一些 action 常量 , 开发者也可以自定义 action 。 一般来说 , 自定义的 action 应该以 application 的包名作为前缀 , 然后附加特定的大写字符串 , 例如 "cn 。 xing 。 upload 。 action 。 UPLOAD_COMPLETE" 就是一个命名良好的 action 。
Intent 类的 setAction() 方法用于设定 action,getAction() 方法可以获取 Intent 中封装的 action 。
以下是 Intent 类中预定义的部分 action:
ACTION_CALL-- 目标组件为 activity, 代表拨号动作 ;
ACTION_EDIT-- 目标组件为 activity, 代表向用户显示数据以供其编辑的动作 ;
ACTION_MAIN-- 目标组件为 activity, 表示作为 task 中的初始 activity 启动 ;
ACTION_BATTERY_LOW-- 目标组件为 broadcastReceiver, 提醒手机电量过低 ;
ACTION_SCREEN_ON-- 目标组件为 broadcast, 表示开启屏幕。
Intent 的 Category 属性
category 属性也是一个字符串 , 用于指定一些目标组件需要满足的额外条件。 Intent 对象中可以包含任意多个 category 属性。 Intent 类也预定义了一些 category 常量 , 开发者也可以自定义 category 属性。
Intent 类的 addCategory() 方法为 Intent 添加 Category 属性 ,getCategories() 方法用于获取 Intent 中封装的所有 category 。
以下是 Intent 类中预定义的部分 category:
CATEGORY_HOME-- 表示目标 activity 必须是一个显示 homescreen 的 activity;
CATEGORY_LAUNCHER-- 表示目标 activity 可以作为 task 栈中的初始 activity, 常与 ACTION_MAIN 配合使用 ;
CATEGORY_GADGET-- 表示目标 activity 可以被作为另一个 activity 的一部分嵌入。
Intent 的 Data 属性
data 属性指定所操作数据的 URI 。 data 经常与 action 配合使用 , 如果 action 为 ACTION_EDIT,data 的值应该指明被编辑文档的 URI; 如果
action 为 ACTION_CALL,data 的值应该是一个以 "tel:" 开头并在其后附加号码的 URI; 如果 action 为 ACTION_VIEW,data 的值应该是一个以 "http:" 开头并在其后附加网址的 URI 。。。
Intent 类的 setData() 方法用于设置 data 属性 ,setType() 方法用于设置 data 的 MIME 类型 ,setDataAndType() 方法可以同时设定两者。 可以通过 getData() 方法获取 data 属性的值 , 通过 getType() 方法获取 data 的 MIME 类型。
Intent 的 Extra 属性
通过 Intent 启动一个 component 时 , 经常需要携带一些额外的数据过去。 携带数据需要调用 Intent 的 putExtra() 方法 , 该方法存在多个重载方法 , 可用于携带基本数据类型及其数组 , String 类型及其数组 , Serializable 类型及其数组 ,Parcelable 类型及其数组 , Bundle 类型等。 Serializable 和 Parcelable 类型代表一个可序列化的对象 , Bundle 与 Map 类似 , 可用于存储键值对。
Intent 的 Flag 属性
flag 属性是一个 int 值 , 用于通知 android 系统如何启动目标 activity, 或者启动目标 activity 之后应该采取怎样的后续操作。 所有的 flag 都在 Intent 类中定义 , 部分常用 flag 如下 :
FLAG_ACTIVITY_NEW_TASK-- 通知系统将目标 activity 作为一个新 task 的初始 activity;
FLAG_ACTIVITY_NO_HISTORY-- 通知系统不要将目标 activity 放入历史栈中 ;
FLAG_FROM_BACKGROUND-- 通知系统这个 Intent 来源于后台操作 , 而非用户的直接选择。。。
IntentFilter 类
IntentFilter 类表示 Intent 过滤器 , 大部分情况下 , 每一个 component 都会定义一个或多个 IntentFilter, 用于表明其可处理的 Intent 。
一般来说 ,component 的 IntentFilter 应该在 AndroidManifest 。 xml 文件中定义。
定义的方法 : 在 <activity>,<receiver>, <service> 元素中增加一个或多个 <intent-filter> 子元素。 如 :
<!-- 声明作为程序入口的 Activity-->
<activityandroid:name=" 。 FirstActivity">
<intent-filter>
<action android:name="android 。 intent 。 action 。 MAIN"/>
<category android:name="android 。 intent 。 category 。 LAUNCHER"/>
</intent-filter>
</activity>
IntentFilter 与隐式 Intent
android 系统处理隐式 Intent 时 , 会比较 Intent 和 IntentFilter 的 action,data, category 属性 , 如果以上 3 个属性全都相符的话 , 则 IntentFilter 所属的 component 就可以作为目标组件的候选 ( 存在多个符合条件的 component 时 ) 。
1 。 测试 action 属性。 intent 最多只能定义 1 个 action, 而 filter 可以定义 1 个或多个 action 。
通过 action 测试的条件为 : filter 定义了 intent 的 action 。 例如 intent 的 action 为 "android 。 intent 。 action 。 MAIN", 则定义了 "android 。 intent 。 action 。 MAIN" 这个 action 的 filter 都能通过 action 测试 ( 当然 , filter 还可以包含更多额外的 action) 。
如果 filter 没有定义 action, 则这个 filter 将阻塞所有 intent 。 如果 intent 没有定义 action, 那么只要 filter 定义了 action 就可以通过 action 测试。
2 。 测试 category 属性。 intent 可以任意多个 category,filter 也可以任意个 category 。 通过 category 测试的条件为 : filter 定义了 intent 的所有 category 。 例如 intent 定义了 "android 。 intent 。 category 。 DEFAULT" 和 "cn 。 xing 。 intent 。 category 。 UPLOAD" 这 2 个 category, 则定义了以上 2 个 category 属性的 filter 才能通过测试 ( 当然 , filter 还可以包含更多额外的 category) 。
根据上面的规则 , 如果一个 intent 没有定义 category, 则所有 filter 都可以通过 category 测试。 但是有一种例外 : 以 startActivity(intent) 方式启动一个 activity 时 , 系统为会 intent 增加一个值为 "android 。 intent 。 category 。 DEFAULT" 的 category, 这就意味着每一个期望通过 category 测试的 activity, 都要在其 filter 中定义 "android 。 intent 。 category 。 DEFAULT"( 除了作为程序入口的 activity) 。
3 。 测试 data 属性。 intent 最多只能定义 1 个 data,filter 则可以定义多个 data 。
通过 data 测试的条件为 :
a 。 如果 intent 没有指定 data 和 data type, 则只有没有定义 data 和 datetype 的 filter 才能通过测试 ;
b 。 如果 intent 定义了 data 没有定义 datatype, 则只有定义了相同 data 且没有定义 datetype 的 filter 才能通过测试 ;
c 。 如果 intent 没有定义 data 却定义了 datatype, 则只有未定义 data 且定义了相同的 datatype 的 filter 才能通过测试 ;
d 。 如果 intent 既定义了 data 也定义了 datatype, 则只有定义了相同的 data 和 datatype 的 filter 才能通过测试。
data 属性是一个 URI, URI 中包含 scheme,host, post 和 path, 典型的 URI 为 :
scheme://host:port/path
scheme, host, post 和 path 都是可选的。 比较 2 个 data 时 , 只比较 filter 中包含的部分。 比如 filter 的一个 data 只是指定了 scheme 部分 , 则测试时只是比较 data 的 scheme 部分 , 只要两者的 scheme 部分相同 , 就视为 " 相同的 data"
使用 Intent 启动组件的优势
1, Intent 为组件的启动提供了一致的编程模型。 无论想要启动的组件是 Activity,Service, 还是 BroadcastReceiver, 都可以使用 Intent 封装启动的意图。
2, 在某些时候 , 应用程序只是想启动具有某种特征的组件 , 并不想和某个特定的组件耦合。 使用 Intent 可以方便的达到这种高层次解耦的目的。
Intent 的 Component 属性
Intent 对象的 setComponent(ComponentNamecomp) 方法用于设置 Intent 的 Component 属性。 ComponentName 包含如下几个构造器 :
ComponentName(Stringpkg, String cls)
ComponentName(Contextpkg, String cls)
ComponentName(Contextpkg, Class<?> cls)
由以上的构造器可知 , 创建一个 ComponentName 对象需要指定包名和类名 -- 这就可以唯一确定一个组件类 , 这样应用程序即可根据给定的组件类去启动特定的组件。 例如 :
ComponentName comp =new ComponentName(FirstActivity 。 this,SecondActivity 。 class);
Intent intent = newIntent();
intent 。 setComponent(comp);
以上三句代码创建了一个 intent 对象 , 并为其指定了 Component 属性 , 完全等价于下面的代码 :
Intent intent = newIntent(FirstActivity 。 this,SecondActivity 。 class);
除了使用 setComponent() 之外 , 还可以使用 setClass(),setClassName() 来显式指定目标组件 , 还可以调用 getComponent() 方法获得 Intent 中封装的 ComponentName 对象。
当程序采用这种形式启动组件时 , 在 Intent 中明确的指定了待启动的组件类 , 此时的 Intent 属于显式 intent, 显式 Intent 应用场合比较狭窄 , 多用于启动本应用中的 component, 因为这种方式需要提前获知目标组件类的全限定名。 而隐式 Intent 则通过 Intent 中的 action,category, data 属性指定目标组件需要满足的若干条件 , 系统筛选出满足所有条件的 component, 从中选择最合适的 component 或者由用户选择一个 component 作为目标组件启动。
如果 Intent 中指定了 ComponentName 属性 , 则 Intent 的其他属性将被忽略。
Intent 的 Action 属性
action 属性是一个字符串 , 代表某一种特定的动作。 Intent 类预定义了一些 action 常量 , 开发者也可以自定义 action 。 一般来说 , 自定义的 action 应该以 application 的包名作为前缀 , 然后附加特定的大写字符串 , 例如 "cn 。 xing 。 upload 。 action 。 UPLOAD_COMPLETE" 就是一个命名良好的 action 。
Intent 类的 setAction() 方法用于设定 action,getAction() 方法可以获取 Intent 中封装的 action 。
以下是 Intent 类中预定义的部分 action:
ACTION_CALL-- 目标组件为 activity, 代表拨号动作 ;
ACTION_EDIT-- 目标组件为 activity, 代表向用户显示数据以供其编辑的动作 ;
ACTION_MAIN-- 目标组件为 activity, 表示作为 task 中的初始 activity 启动 ;
ACTION_BATTERY_LOW-- 目标组件为 broadcastReceiver, 提醒手机电量过低 ;
ACTION_SCREEN_ON-- 目标组件为 broadcast, 表示开启屏幕。
Intent 的 Category 属性
category 属性也是一个字符串 , 用于指定一些目标组件需要满足的额外条件。 Intent 对象中可以包含任意多个 category 属性。 Intent 类也预定义了一些 category 常量 , 开发者也可以自定义 category 属性。
Intent 类的 addCategory() 方法为 Intent 添加 Category 属性 ,getCategories() 方法用于获取 Intent 中封装的所有 category 。
以下是 Intent 类中预定义的部分 category:
CATEGORY_HOME-- 表示目标 activity 必须是一个显示 homescreen 的 activity;
CATEGORY_LAUNCHER-- 表示目标 activity 可以作为 task 栈中的初始 activity, 常与 ACTION_MAIN 配合使用 ;
CATEGORY_GADGET-- 表示目标 activity 可以被作为另一个 activity 的一部分嵌入。
Intent 的 Data 属性
data 属性指定所操作数据的 URI 。 data 经常与 action 配合使用 , 如果 action 为 ACTION_EDIT,data 的值应该指明被编辑文档的 URI; 如果
action 为 ACTION_CALL,data 的值应该是一个以 "tel:" 开头并在其后附加号码的 URI; 如果 action 为 ACTION_VIEW,data 的值应该是一个以 "http:" 开头并在其后附加网址的 URI 。。。
Intent 类的 setData() 方法用于设置 data 属性 ,setType() 方法用于设置 data 的 MIME 类型 ,setDataAndType() 方法可以同时设定两者。 可以通过 getData() 方法获取 data 属性的值 , 通过 getType() 方法获取 data 的 MIME 类型。
Intent 的 Extra 属性
通过 Intent 启动一个 component 时 , 经常需要携带一些额外的数据过去。 携带数据需要调用 Intent 的 putExtra() 方法 , 该方法存在多个重载方法 , 可用于携带基本数据类型及其数组 , String 类型及其数组 , Serializable 类型及其数组 ,Parcelable 类型及其数组 , Bundle 类型等。 Serializable 和 Parcelable 类型代表一个可序列化的对象 , Bundle 与 Map 类似 , 可用于存储键值对。
Intent 的 Flag 属性
flag 属性是一个 int 值 , 用于通知 android 系统如何启动目标 activity, 或者启动目标 activity 之后应该采取怎样的后续操作。 所有的 flag 都在 Intent 类中定义 , 部分常用 flag 如下 :
FLAG_ACTIVITY_NEW_TASK-- 通知系统将目标 activity 作为一个新 task 的初始 activity;
FLAG_ACTIVITY_NO_HISTORY-- 通知系统不要将目标 activity 放入历史栈中 ;
FLAG_FROM_BACKGROUND-- 通知系统这个 Intent 来源于后台操作 , 而非用户的直接选择。。。
IntentFilter 类
IntentFilter 类表示 Intent 过滤器 , 大部分情况下 , 每一个 component 都会定义一个或多个 IntentFilter, 用于表明其可处理的 Intent 。
一般来说 ,component 的 IntentFilter 应该在 AndroidManifest 。 xml 文件中定义。
定义的方法 : 在 <activity>,<receiver>, <service> 元素中增加一个或多个 <intent-filter> 子元素。 如 :
<!-- 声明作为程序入口的 Activity-->
<activityandroid:name=" 。 FirstActivity">
<intent-filter>
<action android:name="android 。 intent 。 action 。 MAIN"/>
<category android:name="android 。 intent 。 category 。 LAUNCHER"/>
</intent-filter>
</activity>
IntentFilter 与隐式 Intent
android 系统处理隐式 Intent 时 , 会比较 Intent 和 IntentFilter 的 action,data, category 属性 , 如果以上 3 个属性全都相符的话 , 则 IntentFilter 所属的 component 就可以作为目标组件的候选 ( 存在多个符合条件的 component 时 ) 。
1 。 测试 action 属性。 intent 最多只能定义 1 个 action, 而 filter 可以定义 1 个或多个 action 。
通过 action 测试的条件为 : filter 定义了 intent 的 action 。 例如 intent 的 action 为 "android 。 intent 。 action 。 MAIN", 则定义了 "android 。 intent 。 action 。 MAIN" 这个 action 的 filter 都能通过 action 测试 ( 当然 , filter 还可以包含更多额外的 action) 。
如果 filter 没有定义 action, 则这个 filter 将阻塞所有 intent 。 如果 intent 没有定义 action, 那么只要 filter 定义了 action 就可以通过 action 测试。
2 。 测试 category 属性。 intent 可以任意多个 category,filter 也可以任意个 category 。 通过 category 测试的条件为 : filter 定义了 intent 的所有 category 。 例如 intent 定义了 "android 。 intent 。 category 。 DEFAULT" 和 "cn 。 xing 。 intent 。 category 。 UPLOAD" 这 2 个 category, 则定义了以上 2 个 category 属性的 filter 才能通过测试 ( 当然 , filter 还可以包含更多额外的 category) 。
根据上面的规则 , 如果一个 intent 没有定义 category, 则所有 filter 都可以通过 category 测试。 但是有一种例外 : 以 startActivity(intent) 方式启动一个 activity 时 , 系统为会 intent 增加一个值为 "android 。 intent 。 category 。 DEFAULT" 的 category, 这就意味着每一个期望通过 category 测试的 activity, 都要在其 filter 中定义 "android 。 intent 。 category 。 DEFAULT"( 除了作为程序入口的 activity) 。
3 。 测试 data 属性。 intent 最多只能定义 1 个 data,filter 则可以定义多个 data 。
通过 data 测试的条件为 :
a 。 如果 intent 没有指定 data 和 data type, 则只有没有定义 data 和 datetype 的 filter 才能通过测试 ;
b 。 如果 intent 定义了 data 没有定义 datatype, 则只有定义了相同 data 且没有定义 datetype 的 filter 才能通过测试 ;
c 。 如果 intent 没有定义 data 却定义了 datatype, 则只有未定义 data 且定义了相同的 datatype 的 filter 才能通过测试 ;
d 。 如果 intent 既定义了 data 也定义了 datatype, 则只有定义了相同的 data 和 datatype 的 filter 才能通过测试。
data 属性是一个 URI, URI 中包含 scheme,host, post 和 path, 典型的 URI 为 :
scheme://host:port/path
scheme, host, post 和 path 都是可选的。 比较 2 个 data 时 , 只比较 filter 中包含的部分。 比如 filter 的一个 data 只是指定了 scheme 部分 , 则测试时只是比较 data 的 scheme 部分 , 只要两者的 scheme 部分相同 , 就视为 " 相同的 data"