Registering a Go app as a protocol handler under Mac OS X

1,749 views
Skip to first unread message

chris...@gmail.com

unread,
Jul 6, 2016, 5:50:02 PM7/6/16
to golang-nuts
Hi,

I'm trying to hook up a Go application to a URL protocol handler in Mac OS X.  I want a user to be able to click on a link such as myapp://foo/bar and have that launch myapp and be able to access the full query parameters.  I've made it as far as getting the OS to register the handler and launch the app.  That's done by bundling the Go binary into a OS X-style .app package with a Info.plist file like this:  https://gist.github.com/chrissnell/db95a3c5ad6ceca4c673e96cca0f7548

The challenge now is to figure out how to reference the query parameters within Go.  I've determined that they're not passed as command-line arguments.   From what I can tell, you have to use Cocoa libraries to get at them  [1].  I don't know Objective-C or Swift, though, so that's where I'm stumbling.

There are cheap hacks to do this with AppleScript [2] but I wanted something more native. 

Has anybody done this?

Chris




taha...@gmail.com

unread,
Feb 19, 2017, 11:12:41 AM2/19/17
to golang-nuts, chris...@gmail.com

Nathan Kerr

unread,
Feb 20, 2017, 12:32:08 PM2/20/17
to golang-nuts, chris...@gmail.com
I managed to get this working.

https://gist.github.com/nathankerr/38d8b0d45590741b57f5f79be336f07c

I don't know what sort of app you are making, so I made a simple gui that displays the url received, with some filler text before any are. I think the non-ui parts should transfer to whatever you are doing.

A few notes:

- main.go lines 3-8 (cgo and import C) are important. They tell go how to build the c and obj-c parts.
- after C.StartURLHandler is called, HandlerURL will be called. HandleURL needs to be non-blocking as it seems to block the whole UI, so put long-running stuff in another go routine. I had to buffer labelText so the a url received at the same time the app starts will not hang the program.
- I had to put C.StartURLHandler before the ui.Main stuff so the first url would not be lost when the app is opened with `open myapp://whatever` and the app was not already running.
- running `make` will setup the app, including building it. You will need to `go get -u github.com/andlabs/ui` before doing so.
- You might need to change the url scheme to something else because you (presumably) already have an app that registers myapp. I didn't think of this earlier as I was trying to follow your question.
- Before trying to open the url, open the app itself. This will register the url scheme with macOS. After doing so, the app will work if it is already running or not.
- I was not able to get cmd-Q to close the app. Just click the close (red) button on the window. This seems to be a limit of the ui package.

This worked for me using go1.8 on macOS 10.12.3 and the latest version of the ui package.

Hope it helps you out.

Nathan

Joe Blue

unread,
Mar 8, 2017, 6:23:05 AM3/8/17
to golang-nuts, chris...@gmail.com
thansk nathan, i will try it out now.

I am curious if anyone else has done this for windows, Linux, Android and IOS ?

I am working on building apps with golang and QT, and need to be able to do it cross platform. QT has aweful support for this, and i think a golang lib that does this, will allow all GUI toolkits using golang to benefit from this.

i am willing to bring it al together into a single library that is agnostic to OS and wraps the special things each OS needs.
Then from your golang code you just call the agnostic lib,

I know this is a bit of a boiling the ocean idea, but the more i looked into it the more i found he differences between OS to be huge.

Please let me knwo what you think ...

joe

satees...@gmail.com

unread,
Dec 13, 2018, 1:03:43 PM12/13/18
to golang-nuts
Hi Joe, Hope you have achieved what you are trying to. Not sure if some one will go through my post. Since it's more than a year from since this conversation was started. 
I have a developed an app in JavaFX. The idea is to use it in win and mac. For win created installer using InnoSetup wich also registers custom handler protocol. The app is working fine. When some one tries to launch the app by click when it is already running, the second instance will start, identify that some instance is already running and will place the input in some temporary folder and shuts down. The already running app with identify the newly added temp input files in temp folder and will append them to its ui.

However this is not the case with Mac. Mac is not launching the second instance, instead it will just brings the already running app to focus and does nothing.
Basically since mac is blocking the app from launching the second instance, my second instance is not getting chance to create the temp file and then die. from where the first instance will pick them up.

I am editing the Info.plist with below entry and building dmg using "Disk Utility"

<key>LSMultipleInstancesProhibited</key>
<false/> 

This seems to be make app launchable  in multiple users sessions. 

Basically the reason for posting this here is, as you guys here are trying to do some thing close and are already ahead by one year, I am hoping some might be able to help me on how to launch second instance using "custom handler protocol". There are many example, but they are while using command prompt with "open -n". My requirement is from custom protocol.

Cheers,
Andey
Reply all
Reply to author
Forward
0 new messages