Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Has there been a change to the way Mac OSX Mavericks handles CFBundleURLName "Custom url" launches for applications?

I created an app which is launched from a custom url in any OSX browser. This worked just fine by adding a standard CFBundleURLName entry to the app's plist.

My application works by reading by parsing some of the parameters on the custom url and then reacting to them.

So for example with a custom url of:

foobar://param1/param2/param3

When clicking on the above url in a browser, OSX would launch my app and pass the actual custom url itself as the first argument to the app. Therefore in the app I could read the first arg and get the url the opened the app, and parse it for params I need.

This works fine in OSX 10.5-10.8, but in 10.9 Mavericks it appears to work slightly differently. Namely that if the application is not already running, it still launches the app but does not pass the custom url as first argument - so the app thinks it's just been launched manually by the user (such as selecting it from launchpad) rather than directly from a browser.

Weirdly, if the application is already open, then clicking the custom url DOES send the url string over to the app as first argument and functionality within the app occurs as expected.

I've tested this across 10.6->10.9 with new and old versions of my app and all exhibit the same behaviour. All work fine on first launch with versions before 10.9 Mavericks, but in 10.9 they don't get the url passed as first arg but then work on 2nd click once already running.

If anyone could shed some light on this I would be very grateful.

like image 282
Mike Driver Avatar asked Nov 11 '22 18:11

Mike Driver


1 Answers

Where do you set up your URL handler? It needs to happen early. If you currently have it in applicationDidFinishLaunching, try to move it to applicationWillFinishLaunching.

The following works for me and logs the URL at launch even when the app is not running before I open the URL in Safari, for example. When I change WillFinishLaunching to DidFinishLaunching, I see exactly the behavior you describe.

@implementation AppDelegate

- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
    NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
    [appleEventManager setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
}

- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
    NSAppleEventDescriptor *obj = [event descriptorForKeyword:keyDirectObject];
    DescType type = [obj descriptorType];
    if (type == typeChar) {
        NSData *data = [obj data];
        if (data) {
            NSString *urlString = [[NSString  alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSURL *url = [NSURL URLWithString:urlString];
            NSLog(@"url: %@", url);
        }
    }
}

@end
like image 151
Marc Liyanage Avatar answered Nov 15 '22 12:11

Marc Liyanage