如何在Mac上将自定义协议映射到应用程序?

41

我正在尝试在Mac上向应用程序注册自定义协议,即:

  1. 用户点击带有“abcdef://some/url/here”的链接
  2. 安装的应用程序启动,并将上述字符串作为第一个参数传递

我已经成功地使用此问题的信息在Windows上完成了这项任务:

如何创建自己的URL协议?(例如so://...)

我希望找到一些不依赖于浏览器的东西,换句话说,在操作系统层面上。 我还想通过shell脚本自动注册此协议,因此希望有一种无需GUI就能实现的方法。

谢谢!

7个回答

25

我之前没有使用过它,但是有一段时间以前我收藏了OS X URL handler to open links to local files,这正是你要找的。

链接中关键的部分是向应用程序的Info.plist添加适当的CFBundleURLTypes,描述了方案。给出的示例如下:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>Local File</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>local</string>
        </array>
    </dict>
</array>

2
我已经在很多地方看到了这个解决方案:但是这个协议处理程序实际上是什么时候注册的呢?用户必须第一次运行应用程序吗? - fatuhoku
是的,您必须运行应用程序以注册处理程序,然后它可以在透明的情况下使用(假设应用程序隐藏其Dock图标)。 - iconoclast
4
由于大多数OS X应用程序是通过复制安装的,因此 Info.plist 文件在复制时会被注册(通常是到 /Applications/Foo 文件夹)。在某些情况下,如果MIME类型或URL方案未能自动注册,则可能需要重新启动 - tresf
这个具体是做什么的?它会将 local:// 注册到应用程序中吗? - Aaron Franke

23
在Mac上,使用AppleScript很容易实现这个操作。最详细的说明在这篇文章中:从网页链接启动脚本。我建议阅读该页面,因为它包含了完整的步骤和可下载的完整工作示例。
基本上,您需要在脚本中创建一个事件处理程序:
on open location this_URL
    display dialog "I'm doing something with this URL: " & return & this_URL
end open location

然后将其保存为应用程序。然后在 Finder 中使用“显示包内容”来编辑 Info.plist 文件。您可以添加一些属性到该应用程序以注册它作为您的协议处理程序。

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>Cliff's handler</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>abcdef</string>
        </array>
    </dict>
</array>

2
这在我的10.8.2上不起作用。我可以使用类似于More Internet for Mac的东西将方案与应用程序关联后添加MissingLink。但是我无法通过上面简单的AppleScript使其工作。如果我运行open local:test,它会显示/Users/username/local:/test不存在 - studgeek
1
好的,这是很好的建议。我似乎已经解决了它。我遇到了完全相同的“不存在”问题,但是只要将整个.app文件移动到另一个目录中,操作系统似乎就能够识别它了。 - counterbeing
5
操作系统什么时候实际注册这个? - fatuhoku
6
好的,我也让它能够工作了。正如@counterbeing所说,只有在将应用程序捆绑包移动到另一个(任意的)位置后,处理程序才会起作用。这感觉很奇怪,因为似乎Mac OS X会在“移动事件”中注册应用程序的协议处理程序。 我能看出这是有道理的,因为大多数应用程序通常只需要用户将其拖放到/Applications目录中即可“安装”。这样一来,所有已安装的应用程序(无论是通过拖放到应用程序目录还是通过.mpkg安装程序移入的)都将注册它们的处理程序。 - fatuhoku
这个到底是怎么工作的?如果我写了 abcdef://test,macOS 是如何调用应用程序的呢?它是一个命令行参数吗?还是其他类型的通信?一旦注册后,我该如何从我的应用程序内部读取这些值? - Aaron Franke

13

这个问题有十年历史(!),但是我通过Google搜索找到了这里,所以我想提一下我刚刚发现的东西。

Platypus 是一个开源工具,可以让你从一个 shell 脚本或其他脚本语言创建独立的“应用程序”。虽然它实际上只是一个脚本包装器,但它确实可以实现一些很酷的东西,比如对话框和菜单栏项目。

关键是,它甚至允许你将你的“应用程序”注册为自己的自定义 URL 方案的处理程序。从文档中可以看到:

注册 URI 方案处理程序使应用程序注册为 URI 方案的处理程序。这些可以是标准的 URI 方案,如 http,也可以是您选择的自定义 URI 方案(例如 myscheme://)。如果您的应用程序是 URI 方案的默认处理程序,则每次打开与该方案匹配的 URL 时,它都会启动打开。然后,URL 作为参数传递给脚本。

设置非常简单。只需提供你的脚本,在高级设置页面输入你想要的方案名称,然后点击构建应用程序(全部自动化)。在方案和斜杠之后的所有内容都将作为参数传递给你的脚本。

例如,你可以使用以下 bash 脚本作为“speak://”协议的处理程序:

#!/usr/bin/env bash
# The 'say' command on macOS will speak the provided text through the speaker
say $1
你可以通过在浏览器中输入 speak://say-something-funny 或使用命令行上的 open 命令来调用它:
$ open "speak://hello-from-the-command-line"

我可以通过open -a App scheme://test来实现,但是简单的形式open scheme://test无法实现,有没有办法定义(如果可能仅使用命令)给定uri-scheme的默认处理程序? - cglacet
1
啊,我找到为什么它不工作了,尽管应用程序没有运行,但我仍然将LinCastor设置为默认值。移除后,这个问题得到了解决。 - cglacet
谢谢,我已经尝试了5个小时来让它工作。The Platypus在2020年12月份是可以工作的。 - Jordan Réjaud

7
截至今天,在Mac上解决这个问题的最佳方法是使用命令行duti,它允许我在一个非常简单的文本文件中定义所有我的关联。以下是所需步骤:

brew install duti

你需要两个东西。首先是要关联的应用程序的包标识符(bundle ids):

mdls -name kMDItemCFBundleIdentifier /Applications/MacVim.app

其次是文件类型的UTI,Apple提供了一个列表,但也可以像这样探索应用程序支持的UTI:

mdls -name kMDItemContentTypeTree /Applications/MacVim.app

现在,在系统中创建一个文本文件,将包标识符与UTI关联起来即可。
# ~/.default-apps.duti
#
# bundle id       UTI                  role
com.apple.Safari  public.html          all
org.vim.MacVim    txmt
org.vim.MacVim    public.ruby-script

注意,我可以将URL处理程序与txmt等文件类型(如Ruby脚本)关联起来。
在该文件中,我跟踪所有我的应用程序首选项,并在完全重新安装或在其他 Mac 上获取帐户时立即复制它们,只需运行:
duti ~/.default-apps.duti

5

Jay回答中链接页面的重要部分是Info.plist中的条目。

我认为使用启动服务,如果只有这个应用程序可以处理特定的URL方案,它将自动打开此应用程序,否则您需要使用Charlie Martin描述的技巧。

我不确定需要执行的默认命令是什么,或者它是否是一个launchctl命令。


4
挖掘这些细节比较困难,但是有一个偏好设置面板叫做RCDefaultApp可以为您处理。我仍然想知道它是如何工作的,将会继续挖掘。

非常感谢 - 这对我来说是一个不需要思考的解决方案,适用于10.9.2。在Sourcetree中打开github-mac://非常有效(这曾经对我有用!) - ptim

0

我对Mac不是很有经验,所以任何帮助都将不胜感激。

尝试在Packages安装程序的后安装脚本中使用duti运行来添加我的自定义协议:

#!/bin/sh
## 
##  add_handlers.sh -- register UTI handlers for the MyApp
##
##  Requires the duti tool
##

./duti -s MyApp myapp

处理程序出现在RCDefaultApp首选项窗格中,但当从我的其他应用程序调用时,它会打开Safari,并在地址栏中询问“是否允许此页面打开“MyApp”?”,并且当单击“允许”时显示错误:

Safari无法打开指定的地址。 Safari无法打开以“myapp:”开头的互联网地址,因为macOS不识别这种类型的地址。

同时,在尝试从终端打开时也会出现以下问题:

deploy@mini-mac-mini ~ % open myapp://

LSOpenURLsWithRole()针对URL myapp://失败,错误代码为-10810。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接