Android SDK Document 框架导读的翻译和注解[7]——Intents and Intent Filters

晨曦之光 发布于 2012/03/09 12:11
阅读 106
收藏 0

Android应用程序中三个主要的组件——Activity, Service, Broadcast receiver——都是由Intent中传递过来的消息激活的, Intent消息传递是这样一个基础手段,它把相同或者不同应用程序的组件后期运行绑定起来。Intent对象本身是一个被动的数据结构,它用来承载一个关于将要执行动作的抽象描述——在 broadcast的情况下,这个Intent是描述是已经发生,并且被通知到的执行动作[比方说开机完毕, 需要执行一个操作], 下面有很多相互独立机制,为每种类型的组件传递Intent:
1. 一个Intent 对象传给Context.startActivity()或者Activity.startActivityForResult() 去启动一个Activity或者利用已存在的Activity执行某项操作.
2.一个Intent 对象传给Content.startService(),初始化一个Service或者为一个正在进行的Service传递新的指示。同样地,一个intent对象传给Context.bindService(),用来建立主动调用的组件和目标Service之间的连接。如果Service尚未运行,则可选择性的启动。
3.Intent对象传递给任意broadcast方法,如Context.sendBroadcast(), Context.sendOrderBroadCast(),或者Context.sendStickyBroadCast(), 这种方式的传递,会将Intent传递给所有感兴趣的Broadcastreceiver. 许多broadcast起源于系统代码。
在上述各情况下,Android系统要找到需要的Activity, Service, 或者是broadcast receiver的集合,从而响应intent消息,并且在需要的情况下初始化这些组件。这些Intent消息没有交集:broadcast intent 只送往broadcast receiver, 不会送往activity或者service. 一个Intent传给startActivity(), 只会送往activity, 不会送给一个service或者broadcast receiver。

本文档开篇介绍Intent对象. 然后介绍Android中intent和组件的映射规则——Android如何解决那个组件应该接收一个Intent消息。由于Intent没有明显的指明要调用哪个Component, 这个过程包含测试Intent对象和关联潜在目标组件的Intent filter.

 

Intent Objects:
一个Intent对象是信息的集合. 它包含需要接收这个Intent的组件感兴趣的消息(如产生什么样的动作,以及这个动作的数据对象),还包含Android系统需要的附加信息(需要处理 这个Intent的组件分类,以及如何启动目标Activity), 原则上,一个Intent包含如下信息:

Component Name : 处理这个Intent的组件名称。 这是一个ComponentName属性对象——目标组件的类全名(如"com.example.project.app.FreneticActivity")以及在manifest文件中,设置组件Package位 置的信息(如"com.example.project"). 组件名称的package部分和package的名称不一定要完全匹配。
组件名称是可选的, 如果设置了这个组件名称, Intent对象会发送到指定组件的实例。如果没有设置,Android利用其它的信息定位和是的组件目标——查看后续章节的 Intent Resolution.
组件的名称通过setComponent(), setClass(), setClassName()设置,通过getComponent读取。


Action :它是将要执行动作的字符串名称——对于Broadcast Intent, 发生的Action不断上报。 Intent类定义了许多Action 常量,包括下面的:
【这里是一个表格.后面去移植】
可以查看API,可以发现预先定义的一些Action常量. 其它的一些Actions定义在Android api的其他地方,可以在自己的应用中,自定义可以被组件激活的Action字符串。这些自定义的需要将应用程序的包名作为前缀, 如"com.example.project.SHOW_COLOR".
Action很大程度上决定了Intent的其他部分的组织结构 ——特别是Intent的data和extras属性——如同一个方法名决定了传入的参数和返回值。 鉴于上述原因,明智的做法是:尽可能的使用特别的Action名称,并且和Intent的其他属性紧紧绑定。换句话说,为你的组件用到的Intent对象 定义一个完整的约定,而不是每个Action无规则的各自定义。
Intent中Action的设置是用setAction(),读取采用getAction();

 

Data :指的是操作的数据以及这个数据的MIME类型。不同的Action对应不同的数据说明。 比如,如果Intent的的action属性为ACTION_EDIT, 则为了显示并编辑,Intent的data属性需要包含文档的URI; 如果Intent的ation属性为ACTION_CALL, 则Intent的data属性需要为tel:包含拨打电话的URI. 同样地, 如果Intent的action域为ACTION_VIEW并且Intent的data域为http:URI, 接收Intent的Activity将被调用并且下载和现实这个URI表示的资源。
当匹配一个Intent到一个组件,并且能够处理数据时,除了了解URI外,获知这个数据的MIME类型是很重要的。比如,一个能打开图像文件的组件,不应该用来播放音频文件。
在很多情况下,可以从URI推断出data的类型——特别是content:URIs,它表示数据位于设备中,并且有一个content provider控制(查看separate discussion on consten providers). 但是,数据类型同样可以显示的在Intent对象找哦你个设置. setData()方法仅仅设置数据的URI, setType()方法仅仅设置数据的MIMIE类型,setDataAndType()同时设定URI和MIME类型。通过getData()取URI,通过getType()取MIME类型

Category :指的是一个包含附加信息的String,附加信息是关于应该处理Intent的组件类型。任意数目的category描述都可以防止到一个Intent 对象中. 跟Action的做法类似,intent类也定义了多个catagory常量,如:
【这是一个表....稍后去迁移】
查API文档中的Intent, 可以获得所有Category列表.addCategory()方法将一个Category设置到Intent对象中。removeCategory() 删除一个之前设置的Category. getCategoryies()方法得到当前Intent对象中所有的categories.
Extras : 指的是一个Key-Value对,用来给目标组件传递附加信息,正如某些Action和特定的数据URI一样的对应关系,存在某些特殊的extras, 比如: 一个ACTION_TIMEZONE_CHANGED intent有一个"time-zone" extra定义了一个新时区,ACTION_HEADSET_PLUG 有一个"state" extra 表明耳机是否插上还是拔出,而"name" extra则表明了耳机的类型. 如果你需要实现一个SHOW_COLOR action, color的值需要在extra的key-value对中被设置好。

Intent对象中有一系列的putXXX()方法,可以插入不同种类的extra 数据,同样有一系列getXXX()方法用来读取数据. 这些方法对Bundle对象而言都是平行的. 事实上,这些extras可以用Bundle的形式,通过putExtras()和getExtras()方法插入和存取。
Flags :指的是各种各样的标志。大多数用来告知Android系统如何启动一个Activity(如Activity属于哪个task),如何在启动之后处理这个Activity(如Activity是否在最近的Activities集合中). 所有的这些标志都定义在Intent类中。


Android系统和它所带的应用程序利用Intent对象, 发送系统产生的broadcast并且激活系统定义的component. 想谅解如何结构化一个Intent对象,并激活系统组件,参考:list of intents.

 


1. Intent和Activity关联关系
   通过传递的Intent来决定Activity的启动。Intent和Activity的关系是一对多,比如,传递一个Type为mp3的Intent,可能会让你选

择多个Activity——Android自带的音乐播放或者你自己选择的播放器等。Activity在AndroidManifest.xml中预先定义了与哪个Intent相

关,这样方便后面传递Intent,即可以激活对应的Activity。

2. Intent 和 Activity的全局性.
   无疑可以自定义Activity的Intent-Filter,这样每个应用(可以称为进程吗?)自己搞定自己的事情就OK, 但为了应用之间通信

的方便, 比如,系统已经有了一个音乐播放器Activity,何必自己再实现? 因此只需要构造能让该播放器Activity识别的Intent就

行了。 因此通过一些全局的变量塑造Intent,就实现了Activity的复用。方式是利用Intent中的全局常量,如

Intent.ACTION_MAIN,Intent.CATEGORY_SAMPLE_CODE等,定义到Acitity中,这样大家都能使用这样的Activity了。

简单示例:

private void testPM()
    {
    Intent mainIntent = new Intent("com.ostrichmyself.xxx", null);
    PackageManager pm = getPackageManager();
         List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
         for (int i = 0; i < list.size(); i++)
         {
        ResolveInfo info = list.get(i);
        Log.i("Test Intent---", info.activityInfo.name);
         }
        
    }
   AndroidManifest.xml中定义为:
    <activity android:name=".MyActivity" android:label="myActivity">
      <intent-filter>
           <action android:name="com.ostrichmyself.xxx" />
      </intent-filter>
    </activity>

  

注意TestPM()这段代码可以放在和MyActivity所在的application中,也可以放在其它地方。 原因是Activity是全局的。


原文链接:http://blog.csdn.net/ostrichmyself/article/details/5667301
加载中
返回顶部
顶部