意图和意图过滤器

文章译自:http://developer.android.com/intl/zh-CN/guide/components/intents-filters.html



文章内容


  1. 意图对象
  2. 意图解析
    1. 意图过滤器
    2. 常见情况
    3. 使用意图匹配
  3. 记事本示例



意图和意图过滤器


应用的三个核心组件 — 活动,服务和广播接收器 — 通过消息被激活,该消息被称为“意图”。意图通知是在运行后期绑定相同或不同应用间组件的设备。意图本身,一个Intent对象,是一种数据结构,该结构持有被执行操作的抽象描述,或者,通常在广播的情况下,结构持有描述是将要发生的事情和正在广播的内容。有单独的机制向每个类型的组件传递意图:


 

在任何情况下,Android系统查找适当的活动,服务或一组广播接收器来响应意图,如有需要,并初始化它们。在这些消息系统内没有交叠:广播意图只能被传递给广播接收器,从不会是活动或者服务。传递给startActivity()的意图只能被递送给活动,从不是服务或广播接收器,以此类推。


文章开始介绍意图对象。然后介绍Android系统用来向组件映射意图的规则 — 它如何解析哪个组件应该接收意图消息。对于那些没有显示地指定目标组件的意图,该解析过程涉及对与潜在目标有关系的意图过滤器测试意图。进行意图对象的测试。



1. 意图对象


Intent对象就是一束信息。它包括对接收意图感兴趣的组件信息(比如要执行的动作和操作的数据),加上对Android系统感兴趣的信息(比如应当处理意图的组件类别和如何启动目标活动的指令)。原则上,它包含如下方面:


组件名

应该处理意图的组件名。该字段是一个ComponentName对象 —  由目标组件完整的受限制类名(比如"com.example.project.app.FreneticActivity")和设置在组件所在应用清单文件里的包名组成。组件名的包部分和不必和设置在清单文件里的包名匹配。


组件名是可选的。如果它被设置了,意图对象被传递给指定类的实例。如果它没被设置,android使用意图内的其他信息来查找合适的目标 —  参阅意图解释在文档的后面。


组件名可通过setComponent(),setClass(), 或setClassName()来设置,并由getComponent()读取。


动作

命名字符串,指定要被执行动作 — 或者是, 在广播意图的情况下, 已发生并正在被报告的动作。意图类定义了一些动作常量,包括:



                         常量  目标组件                                     动作
ACTION_CALL 活动发起电话呼叫
ACTION_EDIT活动显示数据供用户编辑
ACTION_MAIN活动启动作为任务的起始活动, 没有数据输入和返回输出
ACTION_SYNC 活动服务器上的数据与移动设备上的数据同步
ACTION_BATTERY_LOW 广播接收器电池低电量警告
ACTION_HEADSET_PLUG 广播接收器耳机被插入设备,或从设备将其拔出
ACTION_SCREEN_ON 广播接收器屏幕已被打开
ACTION_TIMEZONE_CHANGED 广播接收器时区设置发生变化


参阅Intent类内预定义的通用动作常量列表描述。其他的动作被定义在Android API的其他地方。你可以定义自己的动作字符串来激活你的应用内部组件。你自定义的那些动作字符串应该包括应用包名来作为前缀—比如,:"com.example.project.SHOW_COLOR"。


动作在很大程度上决定了意图的其余部分是如何构建的 — 特别是dataextras字段 — 和方法名决定了一组参数和返回值一样。出于此原因,一个好的想法是,使用尽可能具体的动作名并将它们与意图的其他字段紧密相连。话句话说,为你的组件能够处理的意图对象定义一个完整的协议,而不是孤立地定义一个动作。


意图对象内的动作由setAction()设置,通过getAction()读取。


数据

被操作数据URI和该数据的MIME类型。不同的数据匹配不同种类的数据规范。例如,如果动作字段是ACTION_EDIT, 则数据字段可能包含供编辑显示的文件URI。如果动作是ACTION_CALL, 数据字段则可能是一个带有被叫号码的tel:URI。类似地 , 如果动作是ACTION_VIEW,数据字段是一个http:URI, 接收意图的活动将被调起来下载并显示任何由该URI引用的数据。


当对有能力处理数据的组件进行意图匹配时,通常,重要的是,除了知道它的URI,还要知道数据的类型(数据的MIME类型)。例如,能够显示图片的组件不应该被调用来播放音频文件。


在很多情况下,数据类型能够可从URI推断出来 — 尤其是content: URIs,它们暗示着数据位于设备上,并由一个内容提供者控制着(参阅对内容提供者的单独讨论)。但是,类型也可以被显示地设置在意图对象里。setData()方法仅指定数据作为URI,setType()仅指定数据作为MIME类型,然后setDataAndType()

指定数据既是URI又是MIME类型。URI由getData() 读取,MIME类型则由getType()读取。


类别

它是包含附加的关于应该处理此意图的组件类别的信息字符串。意图对象内可放置任何数量的类别描述。正如动作一样,意图类定义了多个类别常量,包括如下:


              常量
                                                                    含义
CATEGORY_BROWSABLE目标活动可以被浏览器安全地调用,以显示连接所引用的数据 — 例如,图片或邮件信息。
CATEGORY_GADGET活动可以被嵌入到其他承载小工具活动内。
CATEGORY_HOME显示主屏的活动,当设备开启或Home键被按下时用户看到的第一个屏幕。
CATEGORY_LAUNCHER可作为任务的初始活动,并且被列在最顶层的应用启动器里。
CATEGORY_PREFERENCE目标活动为首选项面板。

请参阅Intent类的类别完整清单描述。

addCategory()方法把类别放入意图对象,removeCategory()删除先前添加的类别,getCategories()得到当前意图对象内所有的类别集合。


附加信息

附加信息的键-值对,它应该被递送给处理意图的组件。就像一些动作需要搭配特殊类型的数据URIs一样,一些动作则需要搭配特殊附加信息。例如,ACTION_TIMEZONE_CHANGED意图拥有一个“time-zone”的附加信息,它识别新的时区,ACTION_HEADSET_PLUG拥有一个“state”的附加信息,它表明是插入耳机还是拔掉耳机,同时还有一个“name”的耳机类型附加信息。假如想创造一个SHOW_COLOR动作,那么颜色值应该放在附加的键-值对里。


意图对象拥有一系列的用来插入各类附件数据的put...()方法以及用来读取数据的类似get...()方法集。这些方法使得附加数据并行于Bundle对象。实际上,可以使用putExtras()getExtras() 来安装附加数据及将其读取为Bundle对象。


标志

各种标志。很多标志通知Android系统如何启动活动(例如,活动应属于哪个任务),并在活动被启动后系统该如何对待它们(例如,它是否隶属于当前活动列表)。 所有的这些标志都定义在Intent类里。


Android系统及与之随带的应用使用意图对象向外发送源自系统的广播和激活系统定义的组件。为了解如何构造意图以激活系统组件,请参看意图列表




2. 意图解析



意图可分为两组:

  • 显式意图通过它的名字来指定目标组件 (组件名字域稍后介绍,它拥有一个值集)。由于组件名通常对其他应用的开发者来说是不可知的,所以显式意图一般被用作应用内部的消息 比如, 活动用它来开始一个从属服务或启动一个姊妹活动。
  • 隐式意图不指定目标(组件名字域为空)。隐式意图常被用来启动其他应用内的组件。


Android系统把显式意图递送给指定目标类实例。意图对象内除了组件名外没有其它东西可以决定哪个意图应该来得到该意图。


隐式意图需要不同的类别。在没有指定目标的情况下,Android系统必须查找最适合的组件(或一些组件)来处理该意图 一个单独的活动或服务来执行请求动作或一组广播接收器来响应广播通知。系统是通过把意图对象的内容与意图过滤器进行比较来查找的,然后构造与过滤器有关联的可能接收意图的组件。过滤器公布组件的功能并限定了它可以处理的组件。过滤器公开了组件接收已公布类型的隐式意图的可能性。如果组件没有任何意图过滤器,它只能接收显式意图。带有过滤器的组件能够既能接收显式意图也能接收隐式意图。


对意图对象进行意图过滤器测试时,只有意图对象的三个方面需要进行查询:

动作
数据(URI和数据类型)
类别


附加信息和标志不参与解析哪个组件接收意图的过程。



2.1  意图过滤器


为通知系统它们能够处理哪些隐式意图,活动,服务和广播接收器可以拥有一个活多个意图过滤器。每个过滤器描述组件的一种功能以及该组件愿意接收的一组意图。实际上,它滤进期望类型的意图,而滤出不想要的意图 但是只有不想要的隐式意图(那些没有指定目标类的意图)。 显式意图则常常被递送给它的目标对象,不管它包含了什么;而不询问过滤器。但是,只有在隐式意图能够通过组件过滤器之一对其测试时,它才能被递送给该组件。


针对组件能够做的每件工作及它呈现给用户的每一面,它都有单独过滤器。例如,Note Pad应用示例的NoteEditor活动有两个过滤器—  一个用来开始一条用户可以查看或编辑的指定记录,另一个用来开始一条新的,用户可以填充和保存的空白记录。(Note Pad 的过滤器在稍后的记事本示例 章节里阐述。)


意图过滤器是IntentFilter类实例。然而,因为android系统必须在它启动组件前知道该组件的功能,意图过滤器通常不是以Java代码来设置的,而是在应用的清单文件(AndroidManifest.xml)里作为<intent-filter>元素。(那些通过调用Context.registerReceiver()注册的广播接收器的过滤器可能是一个例外;它们作为IntentFilter对象被直接创建。)


过滤器拥有与意图对象的动作,数据和类别域相平行的域。过滤器用这三个域对隐式意图进行测试。为把意图递送给拥有该过滤器的组件,隐式意图必须通过这三个测试。即便是其中的一个测试没有通过,Android系统也不会把它递送给这个组件— 至少不是基于这样的过滤器组件。然而,由于组件可能拥有多个意图过滤器,即使意图没能通过组件中的一个过滤器,也可能会通过另一个。


下面是三个测试中的每一个细节描述:


动作测试

清单文件内的<intent-filter>元素将动作罗列为<action>的子元素。例如:


<intent-filter . . . >
    <action android:name="com.example.project.SHOW_CURRENT" />
    <action android:name="com.example.project.SHOW_RECENT" />
    <action android:name="com.example.project.SHOW_PENDING" />
    . . .
</intent-filter>

如示例所示,过滤器可能列出了多个动作,而意图只是指定了一个单个动作。列表不能是空的,过滤器至少要包含一个<action>元素,否则它会阻止所有意图通过。


为了通过这个测试,意图内指定的动作必须与罗列在过滤器内的动作中的一个匹配。如果意图和过滤器都没指定动作,结果如下:

  •  如果过滤器没有列出任何动作,便没有任何东西与意图匹配,因而所有意图都不能通过测试。没有意图能够通过过滤器。
  • 另一方面, 没有指定动作的意图可以自动通过测试  只要过滤器内包含至少一个动作。


类别测试

<intent-filter>元素也可以把类别作为其子元素将其列出。例如:


<intent-filter . . . >
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    . . .
</intent-filter>

注意,先前描述的动作和类别常量没有在清单文件中使用。而使用的是完整字符串值。例如,上例中的字符串"android.intent.category.BROWSABLE"对应文档先前提到的CATEGORY_BROWSABLE常量。类似地,字符串 "android.intent.action.EDIT" 对应ACTION_EDIT常量。


对于通过类别测试的意图来说,意图对象里的每个类别都必须与过滤器中一个类别相匹配。过滤器可以包含多余的类别,但它不能遗漏任何一个意图里的类别。


因此,原则上来讲,不含有类别的意图通常应该通过类别测试,不管过滤器里有什么。这在绝大多数情况下是对的。然而,有个列外,Android视所有传递给startActivity() 的隐式意图就好像它们都至少包含一个类别:"android.intent.category.DEFAULT" (CATEGORY_DEFAULT常量)。因此,愿意接收隐式意图的活动必须在它们的意图过滤器里包含"android.intent.category.DEFAULT"。(带有 "android.intent.action.MAIN" 和"android.intent.category.LAUNCHER" 设置的过滤器列外。它们用于标记开始新任务及可在启动器界面内显示的活动。这些过滤器可以在类别列表里包含"android.intent.category.DEFAULT",但不是必须的。稍后请参阅使用意图匹配来了解更多关于这些过滤器的内容。)


数据测试

像动作和类别一样,意图过滤器的数据说明被包含在其子元素里。并且,如同在动作和类别的情况下一样,该子元素可以出现多次,或者根本没有。例如:


<intent-filter . . . >
    <data android:mimeType="video/mpeg" android:scheme="http" . . . /> 
    <data android:mimeType="audio/mpeg" android:scheme="http" . . . />
    . . .
</intent-filter>

每个<data>元素可以指定一个URI和数据类型(MIME媒体类型)。URI的每一部分有独立的属性scheme,host,port,和path

scheme://host:port/path

例如, 下面的URI,

content://com.example.project:200/folder/subfolder/etc

scheme(方案)为“content”,host(宿主)为 "com.example.project",port(端口)为“200”,path(路径)"folder/subfolder/etc"。host和port一起构成了URI授权(authority),如果没有指定host,则忽略port。


这些属性的每一个都是可选的,但它们不是彼此独立的:为使授权有意义,必须指定scheme。为使path有意义,必须指定scheme和授权。


当意图对象内的URI与过滤器内的URI说明比较时,只比较过滤器里URI实际提到的部分。例如,如果过滤器仅指定了scheme,所有带有该scheme的URIs都匹配该过滤器。如果过滤器指定了scheme和授权,但没有path,则所有带有相同scheme和授权的URIs都与此过滤器匹配,不管他们的path如何。如果过滤器指定了scheme,授权和path,只有持有相同scheme,授权和path的URIs与该过滤器匹配。然而,过滤器内的path说明可以包含通配符来要求path的匹配部分。


<data>元素的类型属性指定了数据的MIME类型。在过滤器里它比URI更常见。意图对象和过滤器可以为子类型使用“*”通配符 — 例如,"text/*" 或 "audio/*"—  表明匹配任何子类型。


数据测试要把意图对象内的URI和数据类型与过滤器内指定的URI和数据类型进行比较。规则如下:

  1. 不包含URI或数据类型的意图对象仅能通过同样没指定任何URIs或数据类型的过滤器的测试。
  2. 如果包含URI但没有包含数据类型(以及不能从URI推断出来的类型)的意图对象通过测试,除非其URI与过滤器内的URI匹配且该过滤器同样没有指定类型。这种情况可能只针对像mailto:和tel:这类没有引用实际数据的URIs。

  3. 包含数据类型而没有包含URI的意图对象只能通过那些列出了相同数据类型并同样地没有指定URI的过滤器测试。

  4. 包含URI和数据类型的意图对象(或者数据类型可由URI推断出来)只有在它的数据类型与指定在过滤器中的某个数据类型匹配时,才算通过数据类型部分的测试。只有在它的URI与过滤器中的某个URI匹配或它拥有content:或file:URI并且过滤器中没有指定URI时,才算通过URI部分的测试。换句话说,如果过滤器中只指定了数据类型,则假定该组件支持content: 和file: 数据。


如果意图能够通过一个以上的活动或服务的过滤器,此时可能会询问用户将要激活哪个组件。如果没有发现匹配目标,将触发异常。



2.2  常见情况


上面所示数据测试的最后一条规则,规则(d),反映了组件能够从文件或内容提供者中获取本地数据的可能。因此,组件的过滤器可以只给出数据类型而不必需要明确地指定content: 和file: 方案。这是典型的情况。例如,下面的<data>元素告诉Android,组件可以从内容提供者内获取图片数据并显示它:

由于绝大多数可用的数据是由内容提供者分发的,因此指定数据类型而非URI的过滤器是最常见的。


<data android:mimeType="image/*" />

另外一个常见的配置是带有方案和数据类型的过滤器。例如,下面的<data>元素告诉Android,该组件可以从网络上获取视频数据并显示它:


<data android:scheme="http" android:type="video/*" />


考虑一下,例如当用户在网页上跟进一条连接时,浏览器应用将做何处理。首先,它尝试着显示数据(如同它可以显示一样,如果该连接是一个HTML页面)。如果它不能显示数据,它会用方案和数据类型组建为一个隐式意图并尝试着以此来启动一个能做此项工作的活动。如果没有接收者,它将询问下载管理器来下载数据。这使得它处于内容提供者的控制之下,因此,一个更大的活动池(那些活动的过滤器刚好指定了数据类型)能够对此做出响应。


绝大多数应用不需要引用任何特定数据也能启动。能够启动应用的活动拥有将"android.intent.action.MAIN"指定为动作的过滤器。如果它们出现在应用程序管理器中,它们也要指定 "android.intent.category.LAUNCHER"类别


<intent-filter . . . >
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>


2.3  使用意图匹配


让意图与意图过滤器进行匹配不仅找到目标组件以将其激活,也发现一些关于设备上的组件集合。例如,通过查找所有其过滤器中指定"android.intent.action.MAIN" 动作和"android.intent.category.LAUNCHER" 类别的活动(如上一章节所述),Android系统填充应用程序管理器,其顶层屏幕显示那些用户可以启动的应用程序。然后它会在启动器里显示活动的图标和标签。类似地,系统通过查找其过滤器内带有"android.intent.category.HOME"的活动来发现主屏幕。


应用使用意图匹配是一个类似的方式。PackageManager拥有一组query...()方法集,它们返回所有能够接收特定意图的组件,并且还拥有类似系列的resolve...()方法,这些方法则确定最好的组件来响应意图。例如,queryIntentActivities()返回所有能执行作为参数传递意图的活动列表,queryIntentServices()则返回类似的服务列表;但它们只是列出了能够做出响应的组件。有个类似的方法,queryBroadcastReceivers() ,用来返回类似的广播接收器。




3. 记事本示例



记事本示例能够让用户浏览记录列表,查看列表内单个记录的细节,编辑记录以及添加一条新记录到列表内。该章节着眼于示例清单文件内声明的意图过滤器。(如果你正在使用离线SDK工作,可以找到该示例的全部资源文件,包括它的清单文件,位于<sdk>/samples/NotePad/index.html。如果你正在线查看该文档,那些资源文件位于教程和示例代码 章节这里。)


在清单文件里,记事本应用声明了三个活动,每个都至少带有一个意图过滤器。记事本应用还声明了一个内容提供者,它管理着记录数据。下面是完整的清单文件:


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.android.notepad">
    <application android:icon="@drawable/app_notes"
                 android:label="@string/app_name" >

        <provider android:name="NotePadProvider"
                  android:authorities="com.google.provider.NotePad" />

        <activity android:name="NotesList" android:label="@string/title_notes_list">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.EDIT" />
                <action android:name="android.intent.action.PICK" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.GET_CONTENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            </intent-filter>
        </activity>
        
        <activity android:name="NoteEditor"
                  android:theme="@android:style/Theme.Light"
                  android:label="@string/title_note" >
            <intent-filter android:label="@string/resolve_edit">
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.EDIT" />
                <action android:name="com.android.notepad.action.EDIT_NOTE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.INSERT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
            </intent-filter>
        </activity>
        
        <activity android:name="TitleEditor" 
                  android:label="@string/title_edit_title"
                  android:theme="@android:style/Theme.Dialog">
            <intent-filter android:label="@string/resolve_title">
                <action android:name="com.android.notepad.action.EDIT_TITLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.ALTERNATIVE" />
                <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
            </intent-filter>
        </activity>
        
    </application>
</manifest>


第一个活动,NotesList,不同于其他的活动,因为它操作着记录的目录(记录列表),而非是单一记录。该活动一般作为应用的初始用户界面。正如它的三个意图过滤器所描述的,该活动能够做三件事情


1.

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

该过滤器声明了进入应用的主入口点。标准的MAIN动作是一个入口点 ,它不需要意图里的任何其他信息(例如,不需要数据说明),同时,LAUNCHER类别表明该入口点应该被列在应用程序管理中。


2.

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.PICK" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>

该过滤器声明了该活动能够在记录目录上做的事情。它允许用户查看或编辑目录(通过VIWE和EDIT动作),或者从目录里选取一特定的记录(通过PICK动作)。


<data>元素的mimeType属性指定了这些动作操作的数据类型。它预示着活动能够从保存记事本数据(vnd.google.note)内容提供者内获取多余零个或多个记录项 (vnd.android.cursor.dir)的游标(Cursor)。启动该活动的意图对象将包含一个content: URI,它指定了该活动应该打开的此类型的确切数据。


同时也注意到在该过滤器内提供了DEFAULT 类别。它在这里是因为Context.startActivity()Activity.startActivityForResult()方法视所有的意图都好像包含了DEFAULT 类别 —不过有两个例外:

  • 显式地指定了目标活动的意图
  • 由MAIN动作和LANUCHER类别构成的意图

因此,DEFAULT类别对所有过滤器都是必需的  — 出来那些带有MAIN动作和LAUCHER类别的过滤器。(显式意图不会查找意图过滤器。)


3.

<intent-filter>
    <action android:name="android.intent.action.GET_CONTENT" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

该过滤器说明了活动返回被用户选取的记录的能力,而不需要关于用户应该选自该目录的任何说明。 GET_CONTENT动作类似于PICK动作。无论哪种情况,活动返回用户选取的记录的URI。(每种情况下,该URI被返回给调用了 startActivityForResult()的活动来启动 NoteList活动。)然后,在这里(过滤器中),调用者指定了期望的数据类型,而非用户将要选取的数据目录。


数据类型,vnd.android.cursor.item/vnd.google.note,表明活动能够返回的数据的类型— 单条记录的URI。从返回的URI,用户能够从保存记事本数据的内容提供者中正确地得到一条记录项(vnd.android.cursor.item)的游标。


也就是说,对于上一个过滤器内的PICK动作,数据类型表明了活动可以显示给用户的数据的类型。对于GET_CONTENT过滤器,它表明了活动能够返回给调用者的数据的类型。


鉴于这些功能,下面的意图将解析NotesLsit活动:

action: android.intent.action.MAIN

不用指定数据启动活动。


action: android.intent.action.MAIN
category: android.intent.category.LAUNCHER

不用选择指定的数据启动活动。实际上它是由启动器使用的意图,以此来填充它的顶层列表。所有包含匹配该动作和类别的过滤器的活动被添加到该列表里。


action: android.intent.action.VIEW
data: content://com.google.provider.NotePad/notes

要求活动显示位于content://com.google.provider.NotePad/notes下的所有记录的列表。然后用户可以浏览列表并获取列表内关于记录的信息。


action: android.intent.action.PICK
data: content://com.google.provider.NotePad/notes

要求活动显示一个位于content://com.google.provider.NotePad/notes下的记录的列表。接着用户可以从列表内选取一条记录,然后活动把那条记录的URI返回给启动NoteList活动的活动。


action: android.intent.action.GET_CONTENT
data type: vnd.android.cursor.item/vnd.google.note

要求活动提供一个单独的记事本数据记录项。


第二个活动,NoteEditor,向用户显示一记录条目并允许用户编辑它。如它的两个意图过滤器所述,该活动可以做两件事情:


1.


<intent-filter android:label="@string/resolve_edit">
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />
    <action android:name="com.android.notepad.action.EDIT_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

首先,该活动的主要目的是让用户与单个记录进行交互 — 要么查看记录要么编辑它。(ENIT_NOTE是EDIT的同义词。)意图将包含于MIME类型vnd.android.cursor.item/vnd.google.note相匹配的数据的URI — 就是说,单个指定记录的URI。通常,它将是由NoteList活动的PICK或GET_CONTENT动作返回的URI。


如同前面,这个过滤器给出了DEFAULT类别,目的是该活动可以由没有显式地指定NoteEditor类的意图来启动。

2.

<intent-filter>
    <action android:name="android.intent.action.INSERT" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>

该活动的次要目的是创建一条新记录,该活动把它插入到现有记录目录里。 意图将包含与MIME类型vnd.android.cursor.dir/vnd.google.note 相匹配的数据URI — 也就是说,新记录应该被放置的目录的URI。


鉴于这些功能,下面的意图将解析NoteEditor活动:

action: android.intent.action.VIEW
data: content://com.google.provider.NotePad/notes/ID
要求活动显示由ID标识的记录内容。(关于content: URIs如何指定组的单个成员的细节内容,请参阅内容提供者)。

action: android.intent.action.EDIT
data: content://com.google.provider.NotePad/notes/ID
要求活动显示由ID标识的记录内容,并让用编辑它。如果用户保存修改,活动更新内容提供内的记录数据。

action: android.intent.action.INSERT
data: content://com.google.provider.NotePad/notes
要求活动在记录列表里以content://com.google.provider.NotePad/notes创建一条新的,空的记录,并运行用户编辑它。如果用户保存该记录,它的URI被返回给调用者


最后一个活动,TitleEditor,能使用户编辑记录的标题。这可以由直接调用活动来实现(通过在意图里显式地设置它的组件名),而不使用意图过滤器。但是这里,我们借此机会来展示如何发布可供选择的现有数据的操作:


<intent-filter android:label="@string/resolve_title">
    <action android:name="com.android.notepad.action.EDIT_TITLE" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.ALTERNATIVE" />
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

活动的单一意图过滤器使用自定义动作"com.android.notepad.action.EDIT_TITLE"。该活动必须由一条指定的记录来调用(数据类型为vnd.android.cursor.item/vnd.google.note), 如同先前的VIEW和EDIT动作。然后,这里的活动显示的是含在记录数据内的标题,而不是记录内容本身。


除了支持普通的DEFAULT类别,标题编辑还支持两个其他的标准类别:ALTERNATIVESELECTED_ALTERNATIVE。这些类别标识可以在选项菜单中呈现给用户的活动(很像LAUNCHER类别标识应该在应用程序管理器中呈现给用户的活动)。注意,过滤器还支持一个显式的标签(通过android:label="@string/resolve_title")来更好地控制当它随该活动作为可选的动作呈现给用户正在查看的数据时用户所看到的东西。 (关于这些类别和构建选项菜单的更多信息,请查阅PackageManager.queryIntentActivityOptions()Menu.addIntentOptions()方法。)


鉴于这些功能,下面的意图将解析TitleEditor活动:

action: com.android.notepad.action.EDIT_TITLE
data: content://com.google.provider.NotePad/notes/ID
要求活动显示与记录ID有关联的标题,并允许用户编辑它。


                                                                                               2012年9月12日, 毕




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值