`

Intents and Intent Filters

阅读更多

一个应用程序的3种核心组件--activities,services,和broadcast receivers--都是通过一种叫做intents的消息来激活的。Intent消息是一种用来在相同或不同应用程序的组件之间提供后期运行绑定的一种工具。intent本身是一个Intent对象,是一种消极的数据结构,包含了要被执行的操作的抽象描述--或者,经常以broadcasts(描述的是一种已经发生的并且被广播的东西)的形式出现。分发intents到每种组件有不同的方法:

 

一个Intent对象被传递给Context.startActivity()方法或Activity.startActivityForResult()方法来启动一个activity或者获得一个已经存在的activity来做一些新的事情。(它也能被传递到Activity.setResult()方法来返回信息给调用startActivityForResult()方法的activity。)

 

一个Intent对象被传递给Context.startService()方法来初始化一个service或递交新的指令给一个真正进行的service。相似地,一个intent可以被传递给Context.bindService()方法来在调用者组件和目标服务之间建立连接。如果服务还没有运行的话,它能随意地初始化服务。

 

Intent对象被传递给任何broadcast方法(例如Context.sendBroadcast()Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()方法),然后被递交给所有对它感兴趣的broadcast receivers。许多类型的broadcasts来源于系统代码。

 

在不同情况下,Android系统会找到合适的activity,service或者broadcast receivers集合来相应intent,如果有必要的话对他们进行初始化。这些消息系统不会重叠:Broadcast intents只会发送给broadcast receivers,不会发送给activities或者services。一个传递给startActivity()方法的intent只会传递给activity,不会传递给一个service或者broadcast receiver,等等。

 

这个文档开始于对Intent对象的描述。然后描述Android对组件使用intent的规则--它是如何解析哪个组件应该接收一个intent消息。对于那些没有明确指定名字的目标组件,这个过程参与了,Intent对象依靠intent filters来关联潜在的目标的测试。

 

Intent Objects

一个Intent对象是一个信息集。它包含了组件感兴趣的信息(比如要执行的action和要使用的数据),以及Android系统感兴趣的信息(比如用来处理intent的组件目录和如何启动一个目标activity的指令)。主要包含下面的东西:

 

 

Component name

处理这个intent的组件名。这个字段是一个ComponentName对象--一个目标组件的完全类名的组合(例如"com.example.project.app.FreneticActivity")并且包名设置在应用程序的manifest文件中这个组件所在的地方(例如,"com.example.project")。组件名的包名部分和manifest文件中的包名没有必要匹配。

 

包名是可选的。如果它被设置了,Intent对象被递交到指定的类的实例。如果没有设置,Android使用Intent对象中的其他的信息来定位一个合适的目标--参考Intent Resolution,该文档的后面。

 

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

 

Action

一个字符串命名要被执行的action,--或者,在broadcast intents的情况下,action发生并被报告。Intent类定义了一系列的常量,包含这些:

 

 

Constant Target component Action
ACTION_CALL activity     初始化一个电话
ACTION_EDIT activity 显示数据给用户编辑
ACTION_MAIN activity 启动初始化一个activity并且没有数据输入没有返回输出
ACTION_SYNC activity 同步服务器和移动设备上的数据
ACTION_BATTERY_LOW broadcast receiver  电池电量低的警告
ACTION_HEADSET_PLUG broadcast receiver  耳机插入设备或者拔出设备
ACTION_SCREEN_ON broadcast receiver  屏幕被点亮
ACTION_TIMEZONE_CHANGED broadcast receiver  设置中时区改变了

 

 

参考Intent类,查看为一般action预定义的常量列表。其他的actions被定义在Android API中的其他地方。你也可以定义你自己的action来激活你的应用程序中的组件。那些你创建的需要包含应用程序包名作为前缀--例如:“com.example.project.SHOW_COLOR”。

 

action很大程度上决定了剩下的intent是如何被构造的--特别是datadata字段--尽管一个方法名决定了参数集合和一个返回值。为此,尽可能具体地使用action名,并且将它们与intent中的其它字段紧紧地连接。换句话说,而不是孤立地定义一个action,为你的组件能够处理的Intent对象定义一个完整的协议。

 

Intent对象中的action通过 setAction()  方法来设置,通过getAction()来读取。

 

Data

要被执行的数据的URI和数据的MIME类型。不同的action搭配不同类型的数据说明。例如,如果action字段是ACTION_EDIT,数据字段就包含了要被显示并被编辑的文档的URI。如果action是ACTION_CALL,数据字段是一个"tel:"URI加上要被呼叫的号码。同样地,如果action是ACTION_VIEW,数据字段是一个“http:”URI,接收到的activity会被调用来下载和显示URI指向的数据。

 

当匹配到一个能够处理intent中的数据的组件的时候,很重要的是知道数据的类型(它的MIME类型)还有它的URI--特别地“content:”URIs,它标识着一个存储在设备上并被一个content provider控制着的数据(参考 separate discussion on content providers)。但是类型也可以被明确地设置到Intent对象中。 setData()方法只能指定一个URI数据,setType()方法只能指定一个MIME类型type, setDataAndType()方法既可以指定一个URI也可以指定一个MIME类型type。URI通过 getData()方法读取,类型type通过 getType()方法读取。

 

Category

 

一个字符串包含了关于用来处理intent的组件的类型的额外信息。许多category目录描述能够被放置到一个Intent对象中。因为它为了actions,Intent类定义了许多category常量,包含这些:

 

Constant Meaning
CATEGORY_BROWSABLE 目标activity能够被安全地被浏览器调用,来显示一个链接中相关的数据--例如,一张图或一封email消息。
CATEGORY_GADGET 一个activity能够被嵌套到另一个有小工具的activity。
CATEGORY_HOME 显示主屏幕的activity,即设备打开后用户看到的第一个主屏幕,或者当按下Home键后显示的主屏幕。
CATEGORY_LAUNCHER 一个task中的第一个activity并且在应用程序启动时候在最顶端。
CATEGORY_PREFERENCE 目标activity是一个偏好面板、

 

参考Intent类的描述查看完全的category列表。

 addCategory()方法将一个category放到一个Intent对象中, removeCategory() 方法删除之前添加的category, getCategories() 方法获取当前对象中的所有的category集合。

 

Extras

键对值被当做额外的信息被递交到处理intent的组件。正如一些actions搭配特殊类型的数据URIs,一些搭配特殊的extras。例如,一个 ACTION_TIMEZONE_CHANGED intent拥有一个“time-zone”extra用来标识新的时区, ACTION_HEADSET_PLUG 有一个“state”extra标识耳机现在是插入的还是拔出的,和“name”extra一样也标识着耳机的类型。如果你发明了一个SHOW_COLOR action,那么颜色值会以一个extra键对值被设置。

 

Intent对象有一系列的put...()方法来插入不同类型的extra数据,同样地有一系列的get...()方法来读取数据。这些方法类似Bundle对象中的方法。实际上,extras可以通过Bundle的 putExtras()方法和 getExtras()方法来设置和读取。

 

Flags

不同分类的Flags。许多指示着Android系统如何启动一个activity(例如,activity属于哪个task),在它启动后如何对待处理它(例如,它是否属于最近activities列表)。所有这些flags都定义在Intent类中。

 

Android系统和应用程序以及整个平台雇佣Intent对象发送系统级别的broadcasts和激活系统定义的组件。想知道如何构造一个intent来激活系统组件,查看 list of intents 

 

Intent Resolution

Intents可以被递交到两个组:

 

 

  • 明确的intent通过名字来指明目标组件(之前提到的,有一个值集合的component name field)。由于组件名通常不会被其它应用的开发者知道,明确的intents通常被用在应用程序内部消息传递--例如一个activity启动一个从属的service或者启动一个姐妹activity。

 

 

 

  • 不明确的intent没有指明一个目标(组件名的字段是空白的)。不明确的intents通常被用来激活在其他应用程序中的组件。

 

 

Android递交一个明确的intent给一个指定的目标类的实例。Intent对象中没有东西除了组件名,组件名决定着哪个组件要获得这个intent。

 

不明确的intent需要一个不同的策略。当没有一个指定的目标的时候,Android系统必须找到最好的组件(可能有多个)来处理这个intent--一个单独的activity或者service来执行请求的action或者broadcast receivers集合来响应broadcast广播。这是通过对比intent对象的contents和intent filters,构造能够接收这个intent对象的组件。过滤器宣传一个组件的能力并限制这个组件能够处理的intents。他们将组件的公开的类型对接收到的不明确的intent公开。如果一个组件没有任何的intent filters,它就只能够接收到明确的intent了。一个带有filter的组件能够接收到明确的intent和不明确的intent。

 

当一个Intent对象与一个intent filter进行测试匹配的时候,只有3个方面会被咨询:

 

action

data(包括URI和数据类型)

category

 

extras和flags不参与组件是否接收一个intent的解析。

 

 

Intent filters

为了告知系统他们能够处理哪种不明确的intents,activities,services,和broadcast receivers能够有一个或者多个intent filters。每个filter描述了一个组件的能力,一个组件能够接收的intents集。它实际上是,一个被渴望的类型的intents中的filters,当过滤掉不想要的intents--但是只针对不想要的不明确的intents(即那些没有命名明确目标的类)。一个明确的intent总是被递交到它的目标,无论它包含了什么;filter不会被咨询。但是一个不明确的intent只有在它能够一个组件的filters,才被递交到一个组件。

 

 

一个组件有不同的负责不同工作的filters。它能够展现给用户每一面。例如,Note Pad实例应用程序的NoteEditor activity有两个filters--一个用来启动一个指定的用户能够查看和编辑的笔记,另一个用来启动一个新的,空白的笔记,用户可以填写和保存。(所有的Note Pad的filters会在后面Note Pad Example章节中被描述。)

 

一个intent filter是IntentFilter类的一个实例。然而,由于Android系统在它能够启动一个组件之前,必须知道这个组件的能力,intent filters通常不会以Java代码的方式来设置,而是在应用程序的manifest文件(AndroidManifest.xml)的<intent-filter>标签中。(一个例外是,broadcast receivers的filters是通过调用Context.registerReceiver()方法动态注册的;他们是以IntentFilter对象的方式直接创建的。)

 

一个filter有与一个Intent对象相似的action,data,和category字段。一个不明确的intent在3个区域与filter进行测试匹配。要被递交到组件需要拥有过滤条件,它必须同时通过3个测试。如果就算是仅有一个失败了,Android系统不会将它递交到组件--至少不会以那个filter为基础。然而,由于一个组件可以有多个intent filters,一个intent没有通过一个组件的一个filter,但是可能通过另外一个。

 

3个测试中的每一个都在下面被详细地描述:

 

Action test

manifest文件中的<intent-filter>标签中以<action>作为子标签将actions列出来。例如:

 

<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>

 

 正如例子展示的,当一个Intent对象只有一个action的时候,一个filter可能有多个。filter列表不能为空;一个filter必须包含最少一个<action>标签,否则它将阻塞所有的intents。

 

为了通过这个测试,Intent对象中指定的action必须匹配filter中列出的actions中的一个。如果intent对象或者filter没有指定一个action,结果如下:

 

如果filter没有列出任何的actions,也就是没有东西让intent来匹配,所以所有的intent都会测试失败。没有intent能够通过这个filter。

 

另一方面,一个没有指定action的Intent对象会自动通过测试--只要filter包含了至少一个的action。

 

Category test

一个<intent-filter>标签也列出了category作为子标签。例如:

 

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

 

 注意,在actions和categories之前描述的常量在manifest文件中不会被使用。而使用的是完整的字符串值。例如上面例子中的"android.intent.category.BROWSABLE"字符串对应的是这个文档中之前提到的CATEGORY_BROWSABLE字段。同样地,“android.intent.action.EDIT”对应的是ACTION_EDIT字段。

 

测试一个intent通过category,Intent对象中的每个category必须匹配filter中的一个category。filter可以列出额外的categories,但是不能遗漏intent中的任何一个。

 

原则上,因此,一个没有categories的Intent对象应该总是能够通过这个测试,无论filter中有什么。这基本上是事实。然而,有一个例外,Android对待所有传递给startActivity()方法的不明确的intents,就好像他们包含了至少一个的category:“android.intent.category.DEFAULT”(CATEGORY_DEFAULT常量)。因此,activities想要接受不明确的intents就必须在他们的intent filters中包含“android.intent.category.DEFAULT”。(包含“android.intent.action.MAIN”和“android.intent.category.LAUNCHER”设置的filter是例外。他们标记开始新task的activities并且展现在启动屏幕上。他们能够包含在categories列表上,但是没有必要。)参考后面的Using intent matching获取更多关于这些filters的信息。

 

Data test

像action和categories,一个intent filter的data也被包含在一个子标签中。并且在这些情况下,子标签能够多次出现,或者一次都不出现。例如:

 

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

 

 每个<data>标签可以指定一个URI和一个数据类型data type(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就被忽略。

 

每个这些属性是可选的,但是它们之间不是独立的:一个authority要有意义,一个scheme也必须被指定。一个path要有意义,一个scheme和一个authority必须被指定。当一个Intent对象中的URI与一个filter中指定的URI进行比较,只比较在filter中实际提到的URI部分。例如,如果一个filter只指定一个scheme,所有有这个scheme的URIs匹配这个filter。如果一个filter指定一个scheme和一个authority,但是没有path,无论他们的paths是什么样情况,所有的拥有相同的scheme和authority的URIs匹配。然而,filter中指定的一个path能够包含通配符来要求path的部分匹配。

 

一个<data>标签的type属性指定了data的MIME类型。这在filters中比一个URI更常见。Intent对象和filter都可以为子类型字段使用一个“*”通配符--例如,“text/*”或“audio/*”--标识着任何子类型匹配。

 

Intent对象中的URI和数据类型与filter中指定的一个URI和数据类型的数据测试对比。下面是规则:

 

a.一个既不包含一个URI也不包含一个数据类型的Intent对象只能通过同样没有指定任何URIs或数据类型的filter的测试。

 

b.一个Intent对象包含一个URI但是没有数据类型(并且一个不能从URI推断的类型),只有在它的URI匹配filter中的一个URI,并且filter同样没有指定一个类型,才能通过测试。这种情况只有像mailto:和tel:没有关联实际的数据。

 

c.一个Intent对象包含了一个数据类型但是没有一个URI,只有filter列出相同的数据类型并且同样也没有指定一个URI才能通过测试。

 

d.一个Intent对象包含了一个URI和一个数据类型(或者一个能够从URI中推断的数据类型)只有在它的类型匹配filter中列出的一个类型,才通过了数据类型部分的测试。如果它的URI匹配filter中的一个URI,或者如果它有一个content:或者file:URI并且filter没有指定一个URI。换句话说,如果一个组件的filter只列出一个数据类型,那么就假设它支持content:file:数据。

 

如果一个intent能够通过超过一个的activity或service的filters,用户可能会被问到要激活哪个组件。一个例外是如果没有目标被找到。

 

 

Common cases

上面数据测试中的最后一个规则,规则(d),反应了预期,组件可以从一个文件或者content provider中获取数据。因此,他们的filters能够只列出一个数据类型并不需要明确地命名content:和file: schemes。这是一个典型的例子。一个像下面的<data>标签,例如,告诉Android组件可以从一个content provider获取图像数据并显示它:

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

由于大部分可用的数据通过content provider来分配,指定一个数据类型但是不是一个URI的filters可能是最经常的。

 

另一个通常的构造是,带有一个scheme和一个数据类型的filters。例如,一个像下面的<data>标签,告诉Android,组件可以从网络上获取video数据并显示它:

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

 

考虑,例如,当用户点击一个web页面上的链接,浏览器应用程序做了什么呢?它首先尝试显示数据(如果这个链接指向的是一个HTML页面)。如果它不能显示数据,它把一个不明确的intent和scheme以及数据类型放到一起并尝试启动一个能够做这个工作的activity。如果没有接收者,它要求下载管理器来下载这个数据。把它放在一个content provider的控制之下,这样,一个潜在地更大的activities池(那些只命名一个数据类型的filters)能够响应。

 

大部分应用程序也有一种方式来启动新的,不用关联任何特定的数据。拥有指定了“android.intent.action.MAIN”action的filters的activities能够初始化应用程序。如果它们作为应用程序的代表来启动,他们也需要指定“android.intent.category.LAUNCHER”category。

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

Using intent matching

Intents通过intent filters进行匹配不仅是为了激活一个目标组件。而且也是为了发现一些关于设备上的组件集合的东西。例如,Android系统的应用程序启动器,屏幕的顶层展示了可以被用户启动的应用程序,通过查找所有的带有特定的“android.intent.action.MAIN”action和“android.intent.category.LAUNCHER”category(正如前面章节解释的)。然后在启动器中显示这些activities的图标和名字。同样地,通过在filter中查找“android.intent.category.HOME”来找到主屏幕。

 

你的应用程序也可以以类似的方式来使用intent匹配。PackageManagerquery...()一系列的方法用来返回可以接受一个特定intent的所有组件,同样地,有一系列的resolve...()方法来决定最适合响应一个intent的组件。例如,方法以一个参数的形式返回能够执行这个intent的所有activities的一个列表;queryIntentServices()方法返回的是一个类似的服务的列表。这两个方法都不激活组件,他们只是列出能够响应的组件。针对broadcast receivers有一个类似的方法queryBroadcastReceivers()

 

Note Pad Example

Note Pad示例应用程序让用户可以以一个note列表的方式查看note,查看列表中的每个项目的详细信息,编辑每个项目,在列表中增加新项。这个章节我们深入manifest文件中声明的intent filters。(如果你没有在线,你可以在<sdk>/samples/NotePad/index.html查看这个示例应用程序的所有资源文件,包括manifest文件。如果你在线阅读文档,资源文件在Tutorials and Sample Code章节的here。)

 

在它的manifest文件中,Note Pad应用程序声明了3个activities,每个至少有一个intent filter。它也声明了一个content provider来管理note数据。下面是整个manifest文件:

<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>

 

第一个activity,NotesList,相对其他的activities是最重要的,事实上它管理的是notes的目录(note列表),而不是单独的一个note。它通常为初始化应用程序的用户接口而服务。正如它的3个intent filters描述的,它能够做3件事情:

 

1.

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

这个filter声明了进入Note Pad应用程序的主入口点。标准的Main action是一个不需要Intent任何其它信息的人口点(没有特定的数据,例如),并且LAUNCHER category说明了这个入口点需要被列在启动器应用程序中。

 

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>
 

这个filter声明了activity在一个notes目录中能够做的事情。它能允许用户查看和编辑目录(通过VIEWEDIT actions),或者从目录中挑选一个特定的note(通过PICK action)。

<data>标签中的mimeType属性指定了这些actions能够操作的数据类型。它标识着activity能够从一个容纳Note Pad数据(vnd.google.note)的content provider中获取一个拥有0到多个项目(vnd.android.cursor.dir)的Cursor。启动这个activity的Intent对象包含了一个content:URI,这个URI指定了应该被打开的activity的明确的数据类型。

 

还要注意DEFAULT category在这个filter中也支持。它在这里因为Context.startActivity()方法和Activity.startActivityForResult()方法对待和处理所有的intents假设他们都包含了DEFAULT category--只有两个例外:

 

  • 明确命名目标activity的Intent

 

  • MAINLAUNCHER category构成的Intent

 

因此,所有的filters都要求有DEFAULT category--处理那些带有MAIN action和LAUNCHER category的filter。(Intent filters不会被明确的intents咨询。)

 

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>

 这个filter描述了activity返回一个用户选中的note而不需要任何目录的详细信息的能力。GET_CONTENT action类似于PICK action。activity为用户选中的一个note返回URI。(在不同情况下,它被返回给调用startActivityForResult()方法的activity来启动NoteList Activity。)然而,调用者指定期望的数据类型,而不是用户将要进行选择的数据的目录。

数据类型vnd.android.cursor.item/vnd.google.note,标识activity能够返回的数据类型--一个单独的note的一个URI,调用者能够从包容Note Pad数据(vnd.google.note)的content provider中为一个明确的item(vnd.android.cursor.item)获取一个Cursor。换句话说,之前的filter中的PICK action,它的数据类型标识着activity能够显示给用户的数据的类型。针对GET_CONTENT filter,它标识着activity能够返回给调用者的数据的类型。

 

具备了这些能力,下面的intents能够解析NotesList Activity:

 

action:android.intent.action.MAIN

启动一个activity并不需要指定数据。

 

action:android.intent.action.MAIN

category: android.intent.category.LAUNCHER

启动一个activity并不需要指定选中的数据。这实际上是启动器用来启动的一个应用程序的intent。(这里理解可能有偏差: This is the actual intent used by the Launcher to populate its top-level list)所有带有匹配这个action和category的filters的activities都会被添加到这个列表。

 

action:android.intent.action.VIEW

data:content://com.google.provider.NotePad/notes

让activity以一个列表的形式显示content://com.google.provider.NotePad/notes下的所有notes。用户可以通过列表浏览并获取每个item的信息。

 

action:android.intent.action.PICK

data:content://com.google.provider.NotePad/notes

让activity以一个列表的形式显示content://com.google.provider.NotePad/notes下的notes。用户可以从list中选中一个note,activity会返回item的URI给启动NoteList activity的activity。

 

action:android.intent.action.GET_CONTENT

data type:vnd.android.cursor.item/vnd.google.note

让activity支持Note Pad数据的一个单独item。

 

第二个activity,NoteEditor,展示给用户一个note入口并用户用户编辑它。正如它的两个intent filters,它能做两件事:

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>

 首先,最基本的,这个activity的目的是运行用户与一个单独的note交互--不是VIEW这个note就是EDIT它。(EDIT_NOTE category是EDIT的同义词。)intent包含了原来与MIME类型vnd.android.cursor.item/vnd.google.note进行数据匹配的URI--也就是,一个单独的,特定的note的URI。它是一个被NoteList activity的PICKGET_CONTENT actions返回的典型的一个URI。

正如之前,这个filter列出了DEFAULT category,因此这个activity能够被intents启动,而不需要明确指定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>

 这个activity的第二个目的是让用户创建一个新的note,这个新的note将被INSERT进一个已经存在的notes目录。intent包含用来匹配MIME类型的URI。

vnd.android.cursor.dir/vnd.google.note是note要被放置到的目录的URI。

 

具有了这些能力,下面的intents将会解析NoteEditor activity:

 

action:android.intent.action.VIEW

data:content://com.google.provider.NotePad/notes/ID

让activity根据ID标识来显示note的内容。(更详细的关于,content:URI如何指定一个组中的单独的成员,参考Content Providers。)

 

action:android.intent.action.EDIT

data:content://com.google.provider.NotePad/notes/ID

让activity根据ID标识来显示note的内容,并让用户编辑它。如果用户保存更改,activity会更新content provider中note的数据。

 

action:android.intent.action.INSERT

data:content://com.google.provider.NotePad/notes

让activity在content://com.google.provider.NotePad/notes下的notes列表中创建一个新的,空的note,并允许用户编辑它。如果用户保存note,它的URI会被返回给调用者。

 

最后一个activity,TitleEditor,让用户来编辑一个note的title。这可以通过直接调用activity(通过明确设置intent中的组件名)来实现,而无需使用一个intent filter。但是这里我们抓住机会来展示如何在目前存在的数据上发布可选的操作:

<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唯一的intent filter使用一个叫做“com.android.notepad.action.EDIT_TITLE”的自定义action。它必须在一个特定的note上被调用(数据类型vnd.android.cursor.item/vnd.google.note),像之前的VIEWEDIT actions。然而,这里的activity显示的title包含在note数据中,而不是note内容本身。

 

除了支持通常的DEFAULT category,title editor也支持其它两个标准的categories:ALTERNATIVESELECTED_ALTERNATIVE。这些categories识别能以菜单选项展现给用户的activities(尽管LAUNCHER category识别应用程序启动器中的要被展示给用户的activities )。注意filter也支持一个明确的label(通过“android:label="@string/resolve_title”)来更好地控制用户看到的内容(这里翻译有点问题:to better control what users see when presented with this activity as an alternative action to the data they are currently viewing.)(更多关于这些目录和建立可选菜单的信息,参考PackageManager.queryIntentActivityOptions()方法和Menu.addIntentOptions()方法。)

 

具有了这些能力,下面的intent将会解析TitleEditor activity:

 

action:com.android.notepad.action.EDIT_TITLE

data:content://com.google.provider.NotePad/notes/ID

 

让activity显示和note ID相关的title,并允许用户来编辑这个title。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics