canOpenUrl fails, but openUrl succeed

Viewed 1815

I am facing a strange problem. I am using xcode 7.2, iOS 9, working on real device iphone 4S (not simulator).

I have 2 apps, app1 and app2. app1 is supposed to send data to app2 using an url scheme. app2 has well declared the scheme app1 has referenced the scheme in plist (as it is required in iOS9)

<key>LSApplicationQueriesSchemes</key>
    <array>
        <array>
            <string>OpenLinkMyData</string>
        </array>
    </array>

Here is the code i use :

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) , ^{

            // build the url, using the scheme name, and the data
            // note that json is escaped from bad url chars.
            NSString * MyJsonDataWellEscaped = [[SomeClass getJSonDataToExport]   stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"OpenLinkMyData://%@",MyJsonDataWellEscaped]];

            // Next line should allow test if the app able to manage that scheme is installed.
            // BUT in our case, this allways returning false.
            bool can = [[UIApplication sharedApplication] canOpenURL:url];
            NSLog(@"canOpenUrl = %@", can?@"true":@"false");
         });
// code of the app that do stuff...
}

I get back the following logs : -canOpenURL: failed for URL: "OpenLinkMyData://(myJsonSuff)" - error: "This app is not allowed to query for scheme OpenLinkMyData" canOpenUrl = false

But if i use the following code :

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) , ^{
            // build the url, using the scheme name, and the data
            // not that json is escaped from bad url chars.
            NSString * MyJsonDataWellEscaped = [[Move2MyMHelper getJSonDataToExport]   stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"OpenLinkMyData://%@",MyJsonDataWellEscaped]];

            if([[UIApplication sharedApplication] openURL:url])
                {
                NSLog(@"App launched OK");
                }
            else
                {
                NSLog(@"App not launched");
                }

        });

       // code of the app that do stuff...
}

If I don't check if scheme is available and I use it directly, App2 is well opened and get all data as required. (else if the app2 is not installed, i get the "App not launched" log).

here is the App2 source for receiving the data (which works as awaited) :

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
     NSString *prefixToRemove = @"OpenLinkMyData://";
    if(url != nil && [[url absoluteString] hasPrefix:prefixToRemove])
        {
         NSString * urlStr = [url absoluteString];
         NSString * json = [urlStr substringFromIndex:[prefixToRemove length]];
         json = [json stringByRemovingPercentEncoding];
         NSLog(@"OpenLinkMyData with json  : %@", json);
          }  
    return YES;
}

What is the problem with canOpenUrl in my case ?

Thanks for any help.

2 Answers

A side note regarding this topic...

There is a 50 request limit for protocols that are not registered.

In this discussion apple mention that for a specific version of an app you can only query the canOpenUrl a limited number of times and will fail after 50 calls for undeclared schemes. I've also seen that if the protocol is added once you have entered this failing state it will still fail.

Be aware of this, could be useful to someone.

Related