5

How do you setup and debug URL schemes with Xamarin.Mac?

I added the following to my Info.plist:

Info.plist

I then built an installer package and installed the app. But if I open mytest:// in a browser or run open mytest:// command line, neither launches my app.

Additionally, is there a way to attach the debugger in Xamarin Studio after running mytest://? On Windows I'd use Debugger.Break and Debugger.Attach but those methods don't seem to be implemented in Mono.

jonathanpeppers
  • 26,115
  • 21
  • 99
  • 182

2 Answers2

5

It doesn't directly address your issue, but does the answer to this question help you at all?

Specifically, it addresses using the custom execution command option on your project. You can define a custom command to execute your application in the debugger:

Open 'Project Options', got to the 'Run>Custom Commands' section, add a custom command for 'Execute'

It also mentions the Debugger.Break behaviour:

If your app is running inside the Mono Soft Debugger with Mono 2.11 or later [...], it will set a soft breakpoint for the soft debugger and work as expected


EDIT:

You can call a URL on an already running Mac app... Can you set up a handler to trap the event, set a breakpoint inside and check that your URL is calling the already-running app properly? It might give you a clue to the behaviour or a way to further debug. Something like this:

    public override void FinishedLaunching(NSObject notification)
    {
        NSAppleEventManager appleEventManager = NSAppleEventManager.SharedAppleEventManager;

        appleEventManager.SetEventHandler(this, new Selector("handleGetURLEvent:withReplyEvent:"), AEEventClass.Internet, AEEventID.GetUrl);
    }

    [Export("handleGetURLEvent:withReplyEvent:")]
    private void HandleGetURLEvent(NSAppleEventDescriptor descriptor, NSAppleEventDescriptor replyEvent)
    {
        // Breakpoint here, debug normally and *then* call your URL
    }
Community
  • 1
  • 1
TheNextman
  • 12,428
  • 2
  • 36
  • 75
  • I was launching the app by running `open /Applications/MyApp.app`, so I tried passing `--debug`, but no luck attaching the debugger. I think the complication here is that it is a Mac app, I bet a console app would work fine. Good point on the custom command, if I feel I need to debug I'll use that--I just need to get the custom URL scheme working first, I guess. – jonathanpeppers Oct 21 '13 at 12:53
  • Thanks, it's hitting the breakpoint now when the app is already open, but it doesn't do anything if the app isn't open yet. Any ideas on that? Can't an app get launched from a URL? – jonathanpeppers Oct 22 '13 at 18:09
  • If it's hitting the breakpoint, it sounds like it's set up right. Could be a problem with LaunchServices. Have you read through this thread: http://www.cocoabuilder.com/archive/cocoa/173722-open-my-application-via-safari.html? It has some good info that might help... – TheNextman Oct 22 '13 at 18:39
  • 1
    I finally got it to work, I believe the url scheme was launching another build of the app that would not start (crashed instantly). After figuring this out, it worked as expected. – jonathanpeppers Nov 18 '13 at 22:48
5

As posted by @TheNextman the solution does work but this is a more complete solution. I got the following information from this Xamarin forums thread. As user (and Xamarin employee) Sebastien Pouliot (@poupou) states,

I never used that specific API but the four characters in enums values are common in Apple API.

The four characters (4 bytes) are compiled into an integer. If there's no C# enum already available then you can convert the strings to an integer which this code:

public static int FourCC (string s) {
    return (((int)s [0]) << 24 |
        ((int)s [1]) << 16 |
        ((int)s [2]) << 8 |
        ((int)s [3]));
}

So the complete sample would be as follows,

public override void FinishedLaunching(NSObject notification)
{
    NSAppleEventManager.SharedAppleEventManager.SetEventHandler(this, new Selector("handleGetURLEvent:withReplyEvent:"), AEEventClass.Internet, AEEventID.GetUrl);
}

[Export("handleGetURLEvent:withReplyEvent:")]
private void HandleGetURLEvent(NSAppleEventDescriptor descriptor, NSAppleEventDescriptor replyEvent)
{
    string keyDirectObject = "----";
    uint keyword = (((uint)keyDirectObject[0]) << 24 |
                   ((uint)keyDirectObject[1]) << 16 |
                   ((uint)keyDirectObject[2]) << 8 |
                   ((uint)keyDirectObject[3]));
    string urlString = descriptor.ParamDescriptorForKeyword(keyword).StringValue;
}
Brad Moore
  • 316
  • 5
  • 23