Как установить приложение Какао в качестве веб-браузера по умолчанию?
Я хочу создать приложение, которое запускается по умолчанию, когда пользователь щелкает ссылку HTTP или HTTPS в других приложениях (Mail, iChat и т. д.).
Чтобы создать приложение, которое может выступать в качестве веб-браузера по умолчанию, необходимо выполнить четыре шага. Первые три шага позволяют вашему приложению выступать в качестве обработчика ролей для соответствующих схем URL-адресов (HTTP и HTTPS), а на последнем этапе оно становится обработчиком ролей по умолчанию для этих схем.
1) Добавьте схемы URL-адресов, которые ваше приложение может обрабатывать, в файл info.plist вашего приложения.
Чтобы добавить поддержку http://
и https://
, вам нужно добавить следующее в файл info.plist вашего приложения. Это сообщает ОС, что ваше приложение способно обрабатывать URL-адреса HTTP и HTTP.
<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
в качестве обработчика событий, предполагая, что мы вызываем setEventHandler
из того же объекта, который определяет метод getUrl:withReplyEvent:
.
Вы должны добавить этот код где-нибудь в код инициализации вашего приложения.
NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager];
[em
setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
Некоторые приложения, включая ранние версии Adobe AIR, используют альтернативное событие WWW! / OURL AppleEvent, чтобы запросить, чтобы приложение открывало URL-адреса, поэтому для совместимости с этими приложениями вам также следует добавить следующее:
[em
setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:'WWW!'
andEventID:'OURL'];
4) Установите приложение в качестве браузера по умолчанию.
Все, что мы сделали до сих пор, пока говорило ОС, что ваше приложение - браузер, теперь нам нужно сделать его браузер по умолчанию.
Для этого нам нужно использовать API Launch Services. В этом случае мы устанавливаем наше приложение как обработчик роли по умолчанию для ссылок 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-адресов. Если вы создаете настраиваемую схему URL-адресов, рекомендуется основывать ее на идентификаторе пакета вашего приложения, чтобы избежать конфликтов с другими приложениями. Поэтому, если ваш идентификатор пакета - com.example.MyApp
, вам следует рассмотреть возможность использования URL-адресов x-com-example-myapp://
.
Launch Services является частью CoreServices, а не Carbon. (Таким образом, он переживает 64-битный переход.)
Нет необходимости создавать литерал NSString
, а затем преобразовывать его в CFStringRef
, как в (CFStringRef)@"http"
. Вместо этого напрямую создайте литерал CFString
: CFSTR("http")
.
Можете ли вы опубликовать ссылку для скачивания на пример проекта? Я не совсем понимаю, куда вставлять все фрагменты кода. Кроме того, есть идеи, как добиться этого как приложение Cocoa-AppleScript?
Есть ли что-то дополнительное / отличное, что нужно сделать, чтобы зарегистрировать приложение в качестве почтового приложения?
Стоит отметить, что на шаге № 3 выше регистрация обработчика событий должна происходить в init (или аналогичном). Это НЕ будет работать, если поместить в applicationDidFinishLaunching:
Отличный учебник. Один вопрос: куда идет код из пункта 4? Спасибо
У меня есть приложение, которое запускает JVM через JNI в отдельном потоке. Если я запускаю поток, приложение больше не получает событие (kAEGetURL), если я этого не делаю, оно получает событие нормально. Есть идеи, что не так? Графический интерфейс Cocoa продолжает работать в основном потоке, в то время как у JVM есть собственный.
Если вы просто хотите изменить вспомогательное приложение по умолчанию для http (s), вы можете сделать это в настройках Safari. Там вы найдете раскрывающийся список, который позволит вам выбрать все зарегистрированные приложения-обработчики для http. Чтобы автоматически установить приложение в качестве браузера по умолчанию, см. Предыдущие инструкции.
Чтобы появиться в качестве опции на System Preferences > General > Default web browser
(по крайней мере, для macOS 11), вам необходимо добавить типы документов для HTML и XHTML в Info.plist (после 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>
Скопируйте и вставьте этот код в свой 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
}