Intent类的注释:


一个intent是要被执行的操作的一种抽象的描述,结合Context.Java类中定义的几个方法 ——

[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicabstractvoidstartActivity(Intentintent);
  2. publicabstractvoidsendBroadcast(Intentintent);
  3. publicabstractComponentNamestartService(Intentservice);
  4. publicabstractbooleanbindService(Intentservice,ServiceConnectionconn,intflags);</span></span>

它可以被用来和对应的组件进行通信,是组件间进行通信的中介,其中,intent最重要的作用是用来启动Activity
上述提到的Context.java类中定义的几个方法中,都有一个Intent对象的参数,于是,先来看Intent类的构造方法 Intent类常用的构造方法有如下几个: [java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicIntent(){}
  2. publicIntent(Stringaction){
  3. setAction(action);
  4. /*publicIntentsetAction(Stringaction){
  5. mAction=action!=null?action.intern():null;
  6. returnthis;
  7. }*/
  8. }
  9. publicIntent(Stringaction,Uriuri){
  10. setAction(action);
  11. mData=uri;
  12. }
  13. publicIntent(ContextpackageContext,Class<?>cls){
  14. mComponent=newComponentName(packageContext,cls);
  15. }</span></span>
在这些构造方法中,主要的操作就是为Intent的成员变量赋值,Intent类的成员变量主要有:
[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">privateStringmAction;
  2. privateUrimData;
  3. privateComponentNamemComponent;
  4. privateintmFlags;
  5. privateArraySet<String>mCategories;
  6. privateBundlemExtras;
  7. ......</span></span>
事实上,除了在构造函数中为这些成员变量赋值,还可以利用下列方法为对应的成员变量赋值:
[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicIntentsetAction(Stringaction){}
  2. publicIntentsetData(Uridata){}
  3. publicIntentsetComponent(ComponentNamecomponent){}
  4. publicIntentsetClassName(ContextpackageContext,StringclassName){}
  5. publicIntentsetFlags(intflags){}
  6. publicIntentaddCategory(Stringcategory){}</span></span>
那么,Intent类的这些成员变量分别都是什么意思呢?
Intent的Component属性
Intent类的setComponent(ComponentName component)方法用于设置Intent的Component属性: [java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicIntentsetComponent(ComponentNamecomponent){
  2. mComponent=component;
  3. returnthis;
  4. }</span></span>
该方法接收一个ComponentName 类型的参数,ComponentName类有三个构造函数:
[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicComponentName(Stringpkg,Stringcls){}
  2. publicComponentName(Contextpkg,Stringcls){}
  3. publicComponentName(Contextpkg,Class<?>cls){}</span></span>
由这三个构造函数可知,指定包名和类名便可确定一个组件,事实上,设置Component属性的目的就是指定一个Intent将要被用来与哪个组件进行通信。以下3句代码创建了一个Intent对象,并指定了它的Component属性:
[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">ComponentNamecomp=newComponentName(this,OtherActivity.class);
  2. IntentmIntent=newIntent();
  3. mIntent.setComponent(comp);</span></span>
除了上述这种方式,还可以这样做:
[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">IntentmIntent=newIntent(this,OtherActivity.class);</span></span>
也可以这样做:

[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">IntentmIntent=newIntent();
  2. mIntent.setClassName(this,OtherActivity);
  3. //我们看到setClassName(ContextpackageContext,StringclassName)方法
  4. //内部调用了mComponent=newComponentName(packageContext,className);</span></span>

上文中,我们提到,设置Component属性的目的就是指定一个Intent将要被用来与哪个组件进行通信。所以,当一个Intent对象设置了它的Component属性的值,这个Intent就被称作显示Intent(显示意图)。显式Intent应用场合比较狭窄, 多用于启动本应用中的Component,因为这种方式需要提前获知目标组件类的全类名。
Intent的Action属性
mAction是Intent的一个String类型的成员变量,它代表某一种特定的操作。 Intent类预定义了一些action常量, 开发者可以自定义action, 自定义的action应该以application的包名作为前缀, 然后附加特定的大写字符串, 如"android.intent.action.CALL"。 Intent类的setAction(String action)方法用于设置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属性
mCategories是Intent的一个ArraySet<String>类型的成员变量,category属性用于指定一些目标组件需要满足的额外条件。 Intent对象中可以包含任意多个category属性。 Intent类也预定义了一些category常量, 开发者也可以自定义category属性。 Intent类的addCategory(String category)方法为Intent添加Category属性: [java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicIntentaddCategory(Stringcategory){
  2. if(mCategories==null){
  3. mCategories=newArraySet<String>();
  4. }
  5. mCategories.add(category.intern());
  6. returnthis;
  7. }</span></span>
以下是Intent类中预定义的部分category: CATEGORY_HOME--表示目标activity必须是一个显示homescreen的activity; CATEGORY_LAUNCHER--表示目标activity可以作为task栈中的初始activity,常与ACTION_MAIN配合使用; CATEGORY_GADGET--表示目标activity可以被作为另一个activity的一部分嵌入。
Intent的Extra属性
通过Intent启动一个component时, 经常需要携带一些数据过去。这个工作主要由Intent的Extra属性来完成,它对应的是Intent 的Bundle类型的成员变量 mExtras ,换句话说,这就是给成员变量 mExtras赋值的问题。可以采用两种方式: A、使用putExtra()方法,该方法具有多个重载方法,如putExtra(String name, byte value)、putExtra(String name, String value)、putExtra(String name, byte[] value)、putExtra(String name, float[] value)等,以putExtra(String name, boolean value)为例: [java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">publicIntentputExtra(Stringname,booleanvalue){
  2. if(mExtras==null){
  3. mExtras=newBundle();
  4. }
  5. mExtras.putBoolean(name,value);
  6. returnthis;
  7. }</span></span>
B、
[java] view plain copy
  1. <spanstyle="background-color:rgb(255,255,255);"><spanstyle="font-family:MicrosoftYaHei;font-size:14px;">BundlemBundle=newBundle();
  2. mBundle.putBoolean(......);
  3. mIntent.putExtras(mBundle);
  4. /*publicIntentputExtras(Bundleextras){
  5. if(mExtras==null){
  6. mExtras=newBundle();
  7. }
  8. mExtras.putAll(extras);
  9. returnthis;
  10. }*/</span></span>
可以看到,两种方式实质是一样的,第二种的扩展性相对来说更好一些。
Intent的Data属性
Data属性对应的是 Intent 的 Uri 类型的成员变量 mData ,它用来指定所操作数据的URI。data经常与action配合使用, 如果action为ACTION_EDIT,data的值应该指明被编辑文档的URI; 如果action为ACTION_CALL,data的值应该是一个以"tel:"开头并在其后附加号码的URI; 如果action为ACTION_VIEW,data的值应该是一个以"http:"开头并在其后附加网址的URI ... ... Intent类的setData(Uri data)方法用于设置mData的值,setType()方法用于设置data的MIME类型,setDataAndType()方法可以同时设定两者。
上述简要总结了Intent的常用属性,其中,为Component属性赋了值的Intent被称为显示Intent,Component属性的目的就是指定一个Intent将要被用来与哪个组件进行通信。 那如果Component属性没有被赋值呢? Component属性没被赋值的Intent被称为隐示Intent,这种情况下,一个Intent将被用来与哪个组件进行通信呢?下面来讲IntentFilter
IntentFilter类的注释: ... ...IntentFilter objects are often created in XML as part of a package'sde>AndroidManifest.xmlde>file, usingde>intent-filterde>tags ... ...

IntentFilter通常被使用在应用程序的清单文件中,在一个组件内部以intent-filter节点的形式来定义,采用白名单管理,即只列出愿意接受的intent

那么,这里就涉及到一个匹配规则的问题。

Android组件可以有一个或多个IntentFilter,每个IntentFilter之间相互独立,一个intent只需要和其中一个IntentFilter匹配上即,而只有一个intent的action、Category和data都同时和某个IntentFilter相匹配,才能认为这个intent和IntentFilter相匹配

一、action的验证:

只要intent设置的action全部来源于某个IntentFilter当中,则匹配成功,需要注意的是,如果intent中没有指定action,那么匹配失败。而且区分大小写。

二、Category的验证:如果Intent中的Category集合是Intentfilter中Category的集合的子集时,Intent能通过检查。另外,系统在调用startActivity和startActivityForResult时默认会给所有 Intent 配置 “android.intent.category.DEFAULT” category。所以只要是想接收一个隐式IntentIntentFilter都应该包括"android.intent.category.DEFAULT"category,不然将导致Intent匹配失败。

三、data的验证(主要参考任玉刚的《Android开发艺术探索》一书,谢谢作者):

和action类似,如果过滤规则中定义了data,那么intent中也需要有可匹配的data,data的结构为:

data由两部分组成,mimeType和URI,mimeType指数据类型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等不同的媒体格式,而URI的结构为:

scheme://host:port/path/pathPrefix/pathPattern,如:

content://com.example.project:200/folder/subfolder/etc 和 http://www.baidu.com:80/search/info

scheme:URI的模式,如http、file、content等,无scheme则URI无效

host:URI的主机名,比如www.baidu.com,无host则URI无效

path、pathPrefix和pathPattern表示路径信息

如果要为intent指定完整的data,必须调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法会清除对方已经设置的值,如:intent.setDataAndType(Uri.parse("http://abc"),"video/mpeg");

最后,当我们通过隐式intent启动一个activity时,需要先做一下判断,看是否有activity能够匹配我们的intent,判断的方法有两种:

采用PackageManager的resolveActivity或者Intent的resolveActivity,如果找不到会返回null。如果没有能匹配上的activity并且没有做判断的话,很可能发生ActivityNotFoundException。

... ... (未完待续)

更多相关文章

  1. Android(安卓)NDK c创建新的线程
  2. Android实现KSOAP2访问WebService
  3. Android获取应用信息判断网络连接返回桌面及卸载apk结束进程等的
  4. ANDROID中根据QQ号码或者QQ群号码,跳转到指定的QQ号码聊天或者QQ
  5. Android(安卓)动态申请存储权限
  6. SharedPreferences存储数据的使用方法(转)
  7. Android获取系统储存以及内存信息的方法(二)
  8. Android(安卓)activity exported属性理解
  9. Activity 的Managing Tasks属性

随机推荐

  1. Android(安卓)判断点是否在Path中(含不规
  2. Android新增音频流类型
  3. Android(安卓)利用方向传感器实现 指南针
  4. Android桌面小部件实例 桌面小时钟
  5. Android(总结):控件居中|水平居中|垂直居中
  6. android中小知识点积累
  7. Android(安卓)Adapter
  8. android控件属性
  9. Android(安卓)MVVM快速开发框架(一)
  10. Android(安卓)Listview 报错 'android.R.