【问题标题】:How do you set your Cocoa application as the default web browser?如何将 Cocoa 应用程序设置为默认 Web 浏览器?
【发布时间】:2010-09-08 03:35:09
【问题描述】:

如何将 Cocoa 应用程序设置为默认 Web 浏览器?

我想创建一个应用程序,当用户在其他应用程序(邮件、iChat 等)中单击 HTTP 或 HTTPS 链接时默认启动该应用程序。

【问题讨论】:

标签: objective-c cocoa


【解决方案1】:

macOS Big Sur 及以上

将此代码复制并粘贴到您的 info.plist 中

<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLName</key>
            <string>Web site URL</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>http</string>
                <string>https</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleURLName</key>
            <string>http URL</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>http</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleURLName</key>
            <string>Secure http URL</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>https</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeName</key>
            <string>HTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.html</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeName</key>
            <string>XHTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.xhtml</string>
            </array>
        </dict>
    </array>
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>GIF image</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.compuserve.gif</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>HTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.html</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>XHTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.xhtml</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>JavaScript script</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.netscape.javascript-​source</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>JPEG image</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.jpeg</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>MHTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>org.ietf.mhtml</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>HTML5 Audio (Ogg)</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>org.xiph.ogg-audio</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>HTML5 Video (Ogg)</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>org.xiph.ogv</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>PNG image</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.png</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>SVG document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.svg-image</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>Plain text document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.text</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>HTML5 Video (WebM)</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>org.webmproject.webm</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>WebP image</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>org.webmproject.webp</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>org.chromium.extension</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>document.icns</string>
            <key>CFBundleTypeName</key>
            <string>PDF Document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.adobe.pdf</string>
            </array>
        </dict>
    </array>

您的应用将显示在系统偏好设置中,并将成为默认浏览器

确保你这样做

    func application(_ application: NSApplication, open urls: [URL]) {
// do a for loop, I recommend it
}

【讨论】:

    【解决方案2】:

    为了在System Preferences &gt; General &gt; Default web browser 上显示为一个选项(至少对于 macOS 11),您需要将 HTMLXHTML 的文档类型添加到 Info.plist(在 accepted answer 上已经描述的 4 个步骤之后),像这样:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>HTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.html</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeName</key>
            <string>XHTML document</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.xhtml</string>
            </array>
        </dict>
    </array>
    

    【讨论】:

      【解决方案3】:

      制作一个可以充当默认网络浏览器的应用有四个步骤。前三个步骤允许您的应用充当相关 URL 方案(HTTP 和 HTTPS)的角色处理程序,最后一步使其成为这些方案的默认角色处理程序。

      1) 将您的应用可以处理的 URL 方案添加到应用的 info.plist 文件中

      要添加对http://https:// 的支持,您需要将以下内容添加到应用程序的 info.plist 文件中。这会告诉操作系统您的应用程序能够处理 HTTP 和 HTTP URL。

      <key>CFBundleURLTypes</key>
      <array>
          <dict>
              <key>CFBundleURLName</key>
              <string>http URL</string>
              <key>CFBundleURLSchemes</key>
              <array>
                  <string>http</string>
              </array>
          </dict>
          <dict>
              <key>CFBundleURLName</key>
              <string>Secure http URL</string>
              <key>CFBundleURLSchemes</key>
              <array>
                  <string>https</string>
              </array>
          </dict>
      </array>
      

      2) 编写 URL 处理方法

      当操作系统想要使用您的应用程序打开 URL 时,将调用此方法。将此方法添加到哪个对象无关紧要,这将在下一步中显式传递给事件管理器。 URL 处理程序方法应如下所示:

      - (void)getUrl:(NSAppleEventDescriptor *)event 
          withReplyEvent:(NSAppleEventDescriptor *)replyEvent
      {
        // Get the URL
        NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject] 
          stringValue];
      
        //TODO: Your custom URL handling code here
      }
      

      3) 注册 URL 处理方法

      接下来,告诉事件管理器在想要使用您的应用加载 URL 时调用哪个对象和方法。在此处的代码中,我将self 作为事件处理程序传递,假设我们从定义getUrl:withReplyEvent: 方法的同一对象调用setEventHandler

      您应该将此代码添加到应用程序的初始化代码中。

      NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager];
      [em 
        setEventHandler:self 
        andSelector:@selector(getUrl:withReplyEvent:) 
        forEventClass:kInternetEventClass 
        andEventID:kAEGetURL];
      

      一些应用程序,包括早期版本的 Adob​​e AIR,使用替代 WWW!/OURL AppleEvent 来请求应用程序打开 URL,因此为了与这些应用程序兼容,您还应该添加以下内容:

      [em
        setEventHandler:self 
        andSelector:@selector(getUrl:withReplyEvent:) 
        forEventClass:'WWW!' 
        andEventID:'OURL'];
      

      4) 将您的应用设置为默认浏览器

      到目前为止,我们所做的一切都告诉操作系统您的应用程序是浏览器,现在我们需要将其设为默认浏览器

      我们必须使用启动服务 API 来执行此操作。在这种情况下,我们将我们的应用设置为 HTTP 和 HTTPS 链接的默认角色处理程序:

      CFStringRef bundleID = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier];
      OSStatus httpResult = LSSetDefaultHandlerForURLScheme(CFSTR("http"), bundleID);
      OSStatus httpsResult = LSSetDefaultHandlerForURLScheme(CFSTR("https"), bundleID);
      //TODO: Check httpResult and httpsResult for errors
      

      (最好在更改默认浏览器之前征得用户的许可。)

      自定义网址方案

      值得注意的是,您也可以使用这些相同的步骤来处理您自己的自定义 URL 方案。如果您要创建自定义 URL 方案,最好将其基于您的应用程序的包标识符,以避免与其他应用程序发生冲突。因此,如果您的捆绑包 ID 是 com.example.MyApp,您应该考虑使用 x-com-example-myapp:// URL。

      【讨论】:

      • Launch Services 是 CoreServices 的一部分,而不是 Carbon。 (因此,它在 64 位转换中幸存下来。)
      • 值得注意的是,在上面的第 3 步中,事件处理程序注册必须发生在 init(或类似的)中。如果放在 applicationDidFinishLaunching 中,它将不起作用:
      • 无需创建NSString 文字,然后将其转换为CFStringRef,如(CFStringRef)@"http"。相反,直接创建一个CFString 文字:CFSTR("http")
      • 你能发布一个示例项目的下载链接吗?我不太清楚在哪里粘贴所有代码。另外,您知道如何将其作为 Cocoa-AppleScript 应用程序来实现吗?
      • 将应用程序注册为电子邮件应用程序是否需要做任何额外/不同的事情?
      【解决方案4】:

      如果您只想更改 http(s) 的默认帮助应用程序,您可以在 Safari 偏好设置中进行。在那里你会找到一个下拉菜单,让你选择所有已注册的 http 处理程序应用程序。要自动将应用设置为默认浏览器,请参阅前面的说明。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多