本文翻译自Launch Services Programming Guide,其中带
删除线的API已经被Apple标记为Deprecated。
本章向开发人员和用户介绍有关Launch Services及其API的基本信息。
项目识别
通常,可以通过以下两种方式之一将要操作的项目(例如应用程序,文档或文件夹)标识为Launch Services进行操作:
- 使用 file-system reference(
FSRef
)指定驻留在本地或远程文件系统卷上的文件 - 使用 Core Foundation URL reference(
CFURL
)指定URL(统一资源定位符),通常(尽管不是必须)表示要通过Internet访问的项目
许多Launch Services操作是通过成对的相关函数实现的,其中一个函数接受 file-system reference 作为参数,另一个函数接受URL reference:例如,可以使用LSGetApplicationForItem( LSCopyDefaultApplicationURLForURL )或LSGetApplicationForURL( LSCopyDefaultApplicationURLForURL )函数找到打开项目的首选应用程序。
此外,某些 Launch Services 函数不适用于特定的单个项目,而是适用于由某些标识特征定义的项目系列。这些特征可以包括:
- 四个字符的文件类型代码
- 四个字符的创作者签名
- 文件扩展名
- MIME(多用途Internet邮件扩展)类型
例如,Launch Services函数LSGetApplicationForInfo可以找到由文档的文件类型,创建者签名,文件扩展名或这些特征的任意组合定义的文档系列的首选应用程序。LSCopyApplicationForMIMEType函数查找具有指定MIME类型的项目的首选应用程序。
注意:在OS X版本10.6和更高版本中,将文档绑定到应用程序时,Launch Services不再考虑文件创建者签名。当Launch Services附加到文档时,它会忽略创建者签名。此外,函数
LSCopyKindStringForTypeInfo和LSGetApplicationForInfo会忽略包含创建者签名的参数。
项目信息
某些Launch Services 函数会返回有关某个项目或一系列项目的请求信息。这可以包括:
- 项目的文件类型
- 项目的创作者签名
- 项目的文件名扩展名
- 项目的显示名称:用于向用户显示其名称的字符串(例如在Finder或Dock中)
- 项目的种类字符串:用于表征其一般性质的字符串(例如,在Finder的“显示简介”窗口或Finder的列表视图的“种类”列中),例如
Application
,Folder
,Alias
,JPEG Picture
,QuickTime Movie
或FrameMaker Document
- 描述项目各种属性的标志,包括:
- 它是纯文件(而不是目录,磁盘卷宗或UNIX符号链接)吗?
- 它是可执行应用程序吗?
- 如果是应用程序,它可以在OS X中本地运行吗?
- 如果是应用程序,是否需要Classic emulation环境?
- 如果某个应用程序可以在本机环境或Classic emulation中运行,那么它会选择一个环境还是另一个环境?
- 它是可编写脚本的应用程序吗?
- 它是容器(例如目录,程序包或磁盘卷宗)吗?
- 它是打包目录吗?
- 它是磁盘卷宗的根目录吗?
- 是别名吗?
- 它是UNIX符号链接吗?
- 它是不可见的(即在Finder中不会显示给用户)吗?
- 它具有隐藏的文件扩展名吗?
启动服务数据库
Launch Services 维护一个中央数据结构,即 Launch Services 数据库,在其中记录有关应用程序以及它们能够打开的文档文件和URL的种类的所有相关信息。每当系统知道一个新应用程序时(例如,当用户将其从安装磁盘拖到“应用程序”文件夹中时),该应用程序就会在Launch Services中注册,该服务会将有关该应用程序的所需信息复制到其数据库中。然后,Launch Services可以使用此信息来确定用于打开给定文档文件或URL的首选应用程序。
Launch Services的属性列表键
Launch Services 从应用程序的 bundle 信息属性列表 Info.plist
或对于单文件应用程序,从应用程序资源分支中的plst
资源获取有关应用程序所需的信息。表1-1显示了相关的键。 (有关这些键和其他property-list 键的详细信息,请参阅 Runtime Configuration Guidelines 。)
CFBundleDisplayName
键指定应用程序的显示名称;可以通过将其包含在相应的.lproj
子目录的InfoPlist.strings
文件中来对其进行本地化。
CFBundleIconFile
标识包含用于在屏幕上显示应用程序的图标的文件。
CFBundleIdentifier
定义应用程序的bundle identifier
,这是用于在运行时查找其bundle的唯一标识字符串。
CFBundleSignature
是应用程序的创建者签名,它是一个四个字符的代码,用于标识属于该应用程序的文档文件。
LSRequiresCarbon
,LSPrefersCarbon
,LSRequiresClassic
,LSPrefersClassic
,LSBackgroundOnly
和LSUIElement
这些键指定了应在其运行应用程序环境的各个方面要求。这些键中任何一个的字符串值“ 1”都将相应的属性声明为true。 (在OS X 10.2或更高版本中,这些键也可以采用Boolean或Number类型的值,而不是String,但是在较早的系统版本中不支持此类值。)
LSRequiresCarbon
,LSPrefersCarbon
,LSRequiresClassic
和LSPrefersClassic
键是互斥的:最多可以将其中之一设置为“ 1”。您可以通过Launch Services函数 LSCopyItemInfoForRef 和 LSCopyItemInfoForURL 返回的项目信息记录的flags字段,获取有关这四个键的值的信息。 LSRequiresCarbon
指定该应用程序必须在OS X中本机运行,并且不能在Classic emulation中运行; LSRequiresClassic
表示相反的意思。 LSPrefersCarbon
和LSPrefersClassic
表示该应用程序可以在任一环境中运行,但优先选择一个环境; Finder通过在应用程序的“显示简介”窗口中显示一个标记为“Open in the Classic environment”的复选框,为用户提供使用哪种环境的选择,该复选框最初是根据应用程序自身指定的键来选择或取消选择的。
注意:在名称
LSRequiresCarbon
和LSPrefersCarbon
中使用Carbon一词具有误导性,因为这些键实际上表示该应用程序需要或倾向于在MacOSX中本地运行,而不管它是否专门基于Carbon。尤其是LSRequiresCarbon
可以很好地适用于Cocoa或Carbon应用。还请注意,bundle 信息属性列表中的LSRequiresCarbon
标志与 item-information记录中的kLSItemInfoIsNativeApp
标志之间的含义存在细微差别:前者指示应用程序必须在本机运行,不能在Classic environment中运行,而后者则表示该应用程序能够在本机运行。设置了kLSItemInfoIsNativeApp
的应用程序也可能能够在Classic environment中运行,具体取决于kLSItemInfoPrefersNative
和kLSItemInfoPrefersClassic
标志的设置。
如果四个键都不设置为“ 1”,则Launch Services通过其他方式推断应用程序的必需或首选环境:
- 如果该应用程序是bundle,则假定它是本机Mac应用程序,并且本机运行(等效于
LSRequiresCarbon
)。 - 如果该应用程序未bundle,并且其资源派生包含
plst
或carb
资源,则假定该应用程序与任一环境兼容,但更喜欢本机运行(等效于LSPrefersCarbon
)。 - 如果该应用程序未budnle,并且没有
plst
或carb
资源,则假定该应用程序是无法在本地运行的Classic应用程序(等效于LSRequiresClassic
)。
就Launch Services而言,最重要的属性列表键是CFBundleDocumentTypes
和CFBundleURLTypes
。与这些键中的每个键关联的值是一个字典数组(分别是 type-definition 和 scheme-definition 字典),每个字典都声明了应用程序准备处理的文件或URL 类型。 Launch Services使用此信息来确定要使用哪个应用程序打开给定的文件或URL。
文件类型
type-definition 字典定义了文件类型,即应用程序可以处理的文件系列。 表1-2显示了此词典中的相关键。 (有关type-definition字典中的这些键和其他键的更多详细信息,请参阅 Runtime Configuration Guidelines 。)
CFBundleTypeName
键指定文件类型的种类字符串,这是一种用户可见的描述,用于在屏幕上(例如,在Finder的“显示简介”窗口中或在Finder的列表视图的“种类”列中)表征该类型的文档。可以通过将其包含在相应的.lproj
子目录的InfoPlist.strings
文件中来对其进行本地化。
CFBundleTypeIconFile
标识包含用于在屏幕上显示此类型文档的图标的文件。 LSTypeIsPackage
指定文档是打包的bundle(true)还是单个文件(false)。
属于某个给定文件类型的文件可以通过其文件类型,文件扩展名或MIME类型来表征。type-definition字典中的CFBundleTypeOSTypes
键指定了一个由四个字符组成的文件类型代码数组,这些代码描述了这种类型的文档。同样,CFBundleTypeExtensions
指定一个文件扩展名数组,CFBundleTypeMIMETypes
指定一个MIME类型数组。如果相应的文件特性不相关,则可以忽略这些单个键中的任何一个,但是必须存在至少一个键才能使文件类型为非空。要允许应用程序在拖放操作期间接受不受限制的文件类型或扩展名的文件,可以对CFBundleOSTypes
或CFBundleTypeExtensions
分别使用特殊的通配符值****
或*
。 (这些仅在拖放操作中起作用,而在用户通过双击打开文档时则不起作用。)最后,CFBundleTypeRole
键指定应用程序对给定类型的文件所要求的角色,具体可以查看下面的“应用角色”章节。
URL 类型
scheme-definition 字典类似于 type-definition 字典,这里是定义URL类型(应用程序可以处理的URL类型),而不是文件类型。表1-3显示了此类字典中的键。 (有关这些键的更多详细信息,请参阅 Runtime Configuration Guidelines 。)
CFBundleURLName
键指定URL类型的字符串,一种用户可见的描述,用于在屏幕上(例如,在Finder的“显示简介”窗口中或在Finder列表视图的“种类”列中)表征该类型的URL。可以通过将其包含在相应的.lproj
子目录的InfoPlist.strings
文件中来对其进行本地化。 CFBundleURLIconFile
标识包含用于在屏幕上显示此类型URL的图标的文件。
属于某个给定URL类型的URL由其 scheme 来表征,例如http,ftp,mailto或file。 scheme-definition词典中的CFBundleURLSchemes
键指定了一系列表征此类型URL的scheme。
应用角色
在声明文件类型时,应用程序可以针对该类型的文件声明特定的角色,从而定义该应用程序能够对此类文件执行的操作的种类。该角色通过应用程序的类型定义词典中的CFBundleTypeRole
键针对给定的文件类型进行声明。Launch Services 识别三种角色:
Editor
。该应用程序可以读取,呈现,操作和保存给定类型的文件。Viewer
。该应用程序可以读取和显示给定类型的文件,但是不能操纵或保存它们。None
。该应用程序无法处理给定类型的文档。此角色对于声明有关应用程序无法打开的文件类型的信息(例如其抽象名称和图标)很有用。
Launch Services定义了一组LSRolesMask
类型的位掩码常量,表示各种可能的角色。Launch Services函数可以找到某个文件或通个系列的文件(LSGetApplicationForItem ,LSGetApplicationForURL和LSGetApplicationForInfo)的首选应用程序,或者确定给定应用程序是否可以打开指定的文档(LSCanRefAcceptItem 和 LSCanURLAcceptURL
),使用此类型的参数来指定应用程序相对于文件所需的角色。
应用程序注册
所有可用的应用程序必须用户系统上进行注册,以使它们被Launch Services发现,并将其文件绑定和其他信息复制到Launch Services的数据库中。通常,无需显式执行此任务,因为OS X系统软件中内置的各种实用程序和服务会自动处理该任务:
- 内置的后台工具可在系统启动或新用户登录时运行,并自动搜索系统,网络,本地和用户域中的“应用程序”文件夹,并注册在该域中找到的所有新应用程序。 (此操作类似于Mac OS早期版本中的“重建桌面”。)
- Finder会在发现所有应用程序后自动注册它们,例如将它们拖到用户磁盘上或当用户导航到包含它们的文件夹时。
- 当用户尝试打开在Launch Services数据库中找不到首选应用程序的文档时,Finder会显示一个对话框,要求用户选择用于打开文档的应用程序。然后在启动该应用程序之前先注册该应用程序。
尽管有这些自动注册实用程序,有时仍可能需要在Launch Services中显式注册应用程序。例如,尽管鼓励开发人员打包其应用程序,以便仅通过将它们拖到用户磁盘上就可以安装它们,但是某些应用程序可能需要更复杂的自定义安装程序软件。在这种情况下,安装程序应调用Launch Services注册功能之一LSRegisterFSRef或LSRegisterURL
来显式注册应用程序。
注册函数采用布尔参数inUpdate
,当正在注册的应用程序已经存在于Launch Services数据库中时,该参数控制函数的行为。如果此参数为true,Launch Services将无条件重新注册该应用程序,从而替换数据库中可能已经存在的任何先前信息。如果参数为false,则仅当应用程序的当前修改时间比数据库中记录的更新时间更近时,才重新注册该应用程序。
在对应用程序的Launch Services相关信息进行任何重大更改之后,您应该通过将LSRegisterFSRef或LSRegisterURL
的inUpdate
设置为true来显式重新注册应用程序,或者更新应用程序的修改时间以确保将被上述自动注册实用程序进行更新。
注意:您可以在“终端”窗口中使用BSD
touch
命令来更新应用程序的修改时间。例如,命令touch /Applications/TextEdit.app
将TextEdit的修改时间设置为当前时间。
打开操作
Launch Services的主要目的是打开应用程序,文件和URL。确切的完成方式取决于要打开的项目的类型,如以下各节所述。
打开应用程序
当要打开的项目是应用程序(或带有scheme file
的URL指定应用程序)时,Launch Services会检查该应用程序是否已在运行,并相应地继续进行操作:
- 如果该应用程序尚未运行,则Launch Services将其启动并向其发送一个“ oapp”(“open applocation”)Apple事件。应用程序应通过执行其正常的启动处理来响应此事件。
- 如果应用程序已经在运行,则启动服务将其激活(将其带到屏幕的前面)并向其发送一个“ rapp”(“reopen application”)Apple事件。这指示应用程序在必要时采取一些其他措施,以向用户提供已激活状态的视觉反馈:例如,如果没有其他窗口打开,它可能会打开一个空的文档窗口或一个文档创建对话框。
无论哪种情况,Launch Services都将应用程序添加到Apple菜单中的“最近的项目”子菜单中。
打开文件
如果要打开的项目是一个文件(或带有scheme文件的URL指定一个文件),Launch Services必须首先确定要使用哪个应用程序打开该项目。这就是该项目的首选应用。如下文“用户指定的绑定首选项”中所述,OS X用户界面允许用户在文件及其首选应用程序之间指定显式绑定。如果指定了这样的显式绑定,则它优先于其他任何考虑事项;如果不是,则Launch Services将使用一组隐式绑定条件来确定首选应用程序,如下文“首选应用程序”中所述。
确定首选应用程序后,Launch Services将启动或激活它(取决于它是否已在运行),并向其发送一个“ odoc”(“open document”)Apple事件,指示其打开指定的文档。 (如果要打印文件而不是仅打开文件,则发送“ pdoc”(“print document”)Apple事件而不是“ odoc”;对于文件URL,如果应用程序声明使用该URL处理scheme,而是向其发送“ GURL”(“get URL”)Apple事件。)
最后,Launch Services将应用程序和文件(或URL)都添加到Apple菜单中的“最近的项目”子菜单中。
打开URL
如果要打开的项目是带有file
以外scheme的URL,则其打开方式与文件基本相同,但以下情况除外:
- 如“首选应用程序”下所述,用于选择首选应用程序的隐式绑定标准是基于URL的scheme组成部分,而不是基于创建者签名,文件类型或文件扩展名。
- 启动或激活后发送到应用程序的Apple事件是“ GURL”(“get URL”),而不是“ odoc”(“打开文档”)。
启动或激活首选应用程序后,Launch Services将应用程序添加到Apple菜单中的“最近的项目”子菜单中。
启动选项
打开应用程序时(无论是单独打开应用程序还是打开一个或多个文件或URL),您都可以指定各种启动选项来控制启动或激活应用程序的方式。这些可以包括:
- 是在专门指定的应用程序中还是在其自己的首选应用程序中打开文件或URL(如果有)
- 是打印文件或URL(如果有)还是仅打开它们
- 是将应用程序和文件(如果有)添加到Finder的“最近使用的项目”菜单中,还是取消此操作
- 是允许应用程序在后台打开还是失败(如果它是仅后台应用程序)
- 是否在不将应用程序置于前台的情况下打开应用程序
- 是允许应用程序在Classic emulation 环境中打开还是失败(如果它是仅Classic应用程序)
- 是否启动应用程序的新实例,即使另一个实例已经在运行
- 启动后是否隐藏应用程序
- 启动此程序后是否隐藏所有其他应用程序
- 是同步还是异步启动应用程序(请参阅下一节)
同步和异步 启动
您可以在启动应用程序时指定的选项之一是同步还是异步启动它:
- 在同步启动中,控件不会从启动应用程序的Launch Services功能返回,直到应用程序完成其启动顺序(当应用程序的图标在Dock中停止“弹跳”时,向用户直观显示)。
- 在异步启动中,控件立即返回,而Dock中的图标仍在“弹起”。 启动序列完成后,将通过
kEventAppLaunchNotification
类型的Carbon事件通知您的应用程序。 您可以设置相应的事件处理回调,来以适当的方式响应此事件。 在对启动应用程序的Launch Services函数的调用中,您可以提供一个任意的4字节引用常量,该常量将作为通知事件的一部分传递回您的处理程序。
用户指定的绑定首选项
在确定文件或非文件URL的首选应用程序时,Launch Services的第一要务是用户是否为该项目指定了显式绑定首选项。
为文件选择绑定首选项
用户可以通过在Finder中选择项目并选择“显示简介”命令来指定文件的首选应用程序(见图1-1)。
“显示简介”窗口的“打开方式”窗格包含一个弹出菜单,列出了Launch Services数据库中所有声称接受所选项目的已知应用程序(请参见图1-2)。 然后,用户可以从菜单中选择一个应用程序,以成为该项目的首选应用程序(图1-3)。
注意:单个项目的显式绑定首选项不是特定于用户的,而是系统范围的。也就是说,即使其他用户登录,它们仍将继续应用于同一台计算机上的给定项目。
单击“全部更改”按钮(图1-4),可使所选应用程序成为同一类型文件或URL类型的所有项目的首选应用程序,而不仅仅是所选单个项目的首选应用程序。
有时,用户可能希望指定一个首选应用程序,但该应用程序之前没有声明接受打开给定的文件或URL。 (这有时候很有用,例如,在文本编辑器中将文本编码格式的文件(例如HTML)作为未编码文本打开。)“打开方式”窗格的弹出菜单中的“其他”项将打开如图所示的对话框。图 1-5,其中用户可以导航到所需的应用程序。 对话框顶部标记为“显示”的弹出菜单中的“所有应用程序”项允许选择任何所需的应用程序。 推荐的应用程序使那些没有声明接受该项目类型的应用变灰。
为URL选择绑定首选项
没有用于设置非文件URL scheme处理程序的系统级用户界面。 但是,单个应用程序可以允许用户为特定的URL方案选择首选的应用程序。 例如:
- Safari应用程序允许用户通过选择默认的Web浏览器来设置
http:
处理程序。 - Mail应用程序允许用户通过选择默认的电子邮件阅读器来设置
mailto:
处理程序。
首选应用程序
当需要执行以下操作时,Launch Services将执行文件绑定操作:
- 计算用于文件的最佳图标。
- 计算文档的种类字符串,如Finder列表视图和其他一些上下文所示。
- 打开一个文档。
Launch Services使用一系列优先的绑定标准来确定用于打开给定文件或URL的首选应用程序。 它们使用了Launch Services 函数中可用于打开文档文件(LSOpenFSRef,LSOpenFromRefSpec)或URL(LSOpenCFURLRef,LSOpenFromURLSpec),也用了仅查找此类项目的首选应用程序而未实际打开的项目(LSGetApplicationForItem ,LSGetApplicationForURL)。它们还使用了LSGetApplicationForInfo函数,该函数用于查找用于打开由指定标识特征定义的项目系列的首选应用程序。
文件的首选应用程序
对于单个文件(无论是由file-system reference 指定还是带有scheme file
的URL指定),条件如下:
- 如果用户为文件(或文件所属的整个文件类型)指定了显式绑定,则首选应用程序是用户指定的。
- 如果文件具有文件名扩展名(或者已将文件扩展名指定为
LSGetApplicationForInfo的参数),请在Launch Services数据库中找到所有声称接受具有该扩展名的文档的应用程序。 - 如果文件带有四个字符的文件类型(或者已将一个类型指定为参数),请查找所有声称接受该类型文件的应用程序。
- 如果由于步骤2–3而发现一个以上的应用程序,请按照所示顺序应用以下条件:
a. 如果文档带有四个字符的创建者签名(或者如果已将其指定为参数),则优先考虑任何声称接受带有该签名的文档的应用程序(通常是该签名所属的应用程序)。
b. 优先于本机OS X应用程序,而不是在Classic emulation环境中运行的应用程序。
c. 与驻留在引导卷上的应用程序相比,驻留在其他文件系统卷上的应用程序优先。
d. 与驻留在远程卷上的应用程序相比,优先于驻留在本地卷上的应用程序。
f. 如果找到同一应用程序的两个或多个版本,则优先使用CFBundleVersion
标识的具有最新版本号的版本。
如果在应用了上述所有条件之后仍然有两个或多个候选应用程序,则Launch Services将以未指定的方式选择其余的应用程序之一。
注意:条件4a不适用于OS X版本10.6和更高版本。 准则4c和4d不适用于OS X版本10.2和更早版本。 Apple保留在以后的系统版本中更改选择标准的权利。
注意:当要打开的项目是文件系统文件夹时,它将被视为文件,其首选应用程序是Finder。 这提供了一种要求Finder打开显示指定文件夹内容的窗口的便捷方法。
URL的首选应用程序
使用非file
schemes的URL的标准与文件相似,除了搜索基于URL的schemes而不是基于文件特征(例如创建者签名,文件扩展名和文件类型)之外:
- 如果用户已为URL(或它所属的整个URL类型)指定了显式绑定,则首选应用程序是用户已指定的应用程序。
- 如果未指定任何显式绑定,请在Launch Services数据库中找到所有声称接受给定schemes的URL的应用程序。
- 如果在步骤2中找到了多个应用程序,请按照所示顺序应用以下条件:
a. 优先于本机OS X应用程序,而不是在Classic emulation环境中运行的应用程序。
b. 与驻留在引导卷上的应用程序相比,驻留在其他文件系统卷上的应用程序优先。
c. 与驻留在远程卷上的应用程序相比,优先于驻留在本地卷上的应用程序。
d. 如果找到同一应用程序的两个或多个版本,请优先选择具有最新版本号的版本。
e. 如果在应用了上述所有条件之后仍然有两个或多个候选应用程序,则Launch Services将以未指定的方式选择其余的应用程序之一。
注意:条件3b和3c在OS X版本10.2和更早版本中不适用。 Apple保留在以后的系统版本中更改选择标准的权利。