6

I am trying to launch the parent ios app from watchkit app. I'm using url scheme to launch the app.But it seems like

-(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply 

is nevered called. It seems like watch app does launch the app in backgound. But the parent app does not handle the watchkit request. I tried my approach in a new project and it works perfectly. Is there any thing I need to pay attention?

I've already tried to Debug>Attach to process>myapp and put a breakpoint inside handleWatchKitExtensionRequest method to confirm if it is called and it isn't called.

Here is the progress, I call openParentApplication when a button is clicked in watch app.

@IBAction func viewOniPhoneAction() {


    let userInfo: [NSObject : AnyObject] = [
        "userID" : user.userID
    ]


    WKInterfaceController.openParentApplication(userInfo, reply: { (userInfo : [NSObject : AnyObject]!, error : NSError!) -> Void in

    })

}

Here is my app delegeate

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
NSDictionary *replyDict = @{@"response": @"done"};
reply(replyDict);
}

I tried reply() in handleWatchKitExtensionRequest but I got this error in reply block from watch app

Error Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x60800026e0c0 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}
cloudy45man
  • 391
  • 2
  • 19
  • Nope, I already tried that one. I believe the problem is in order to start a background task in handleWatchKitExtensionRequest, the method must be called. So that the code inside the method can be executed. It seems like the method isn't even called. – cloudy45man May 21 '15 at 09:05
  • Have you tried this? http://stackoverflow.com/questions/28112445/handlewatchkitextensionrequest-not-responding-to-openparentapplication-in-watchk – John May 21 '15 at 09:08
  • Yes, it does not work. Is there any setting I can check if the parent app and watch app are correctly linked. – cloudy45man May 21 '15 at 09:16
  • Are all bundle identifiers and provisioning profiles in order? – Léo Natan May 21 '15 at 09:50
  • @Leo Yes, everything looks good. – cloudy45man May 21 '15 at 16:26
  • You can't open the parent app from your watch app, it is not supported at this time. In some versions of Xcode, you could get it to work in the simulator with openURL but it will not work with a real watch. Also, you need to use `openParentApplication` from your watch extension to get `handleWatchKitExtensionRequest` to fire in your parent app. – rmp May 21 '15 at 19:00
  • @rmp Ok, even in this case handleWatchKitExtensionRequest should be triggered when I call openParentApplication from my watch app. – cloudy45man May 22 '15 at 02:24
  • Show some code so we can see what you are doing – rmp May 22 '15 at 02:26
  • You must have a reply() in handleWatchKitExtensionRequest and openUrl will NOT work, it is not supported and will not work on a real device, – rmp May 22 '15 at 02:48
  • @rmp I tried to reply in `handleWatchKitRequest` but got an error – cloudy45man May 22 '15 at 03:35

3 Answers3

2

I got it to work!!! Having the same issue....

Just increase the beginBackgroundTaskWithExpirationHandler time to a larger value if you still don't get the data!!! I used 2 secs previously but my network is too weak!!!

I call openParentApplication when a button is clicked in watch app:

[WKInterfaceController openParentApplication:loadDetailChatDataDictionary reply:^(NSDictionary *replyInfo, NSError *error) {

Here is my app delegate:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {

    __block UIBackgroundTaskIdentifier bogusWorkaroundTask;
    bogusWorkaroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // increase the time to a larger value if you still don't get the data!!! I used 2 secs previously but my network is too weak!!!
        [[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
    });
    // --------------------

    __block UIBackgroundTaskIdentifier realBackgroundTask;
    realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        reply(nil);
        [[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
    }];

    NSString *value = userInfo[@"key"];
    if ([value isEqualToString:@"loadRecentChatData"]) {
                 reply(@{@"recents":recents}); // Add your reply here
    }
user1872384
  • 6,886
  • 11
  • 61
  • 103
  • Could ou explain why you need this bogusWorkaroundTask? Not clear fo me why you seem to increase time on it, and not on realBackgorundTask... – blackbox Aug 14 '15 at 09:25
  • 1
    @blackbox the bogus workaround task is there to workaround an issue here sometimes Apple was killing the App even if you had already started a background task. For some reason, starting a bogus task immediately and killing it off after a few seconds functioned to allow the real handler code to establish its own background task before being prematurely cutoff. This solution worked for me as well, however I find that `application:handleWatchKitExtensionRequest:reply:` ceases to be called after several requests are made and the device is locked. – Beltalowda Mar 01 '16 at 16:25
0

handleWatchKitRequest isn't called when you open the app via a URL scheme. It is only called in response to requests made in the WatchKit extension made using openParentApplication:reply:. That's why you aren't seeing it being executed.

bgilham
  • 5,909
  • 1
  • 24
  • 39
  • Sorry for confusion, I use both method to achieve what I want. I use WKInterfaceController openapplication inside watch app and use following to launch the app. -(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply{ [[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"HandlingWatchKitTest://"]] ; } – cloudy45man May 21 '15 at 16:10
0

You will need to wrap your reply in a background task to ensure your parent app has time to respond.

-

(void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *replyInfo))reply{

    UIApplication *app = [UIApplication sharedApplication];

    UIBackgroundTaskIdentifier bgTask __block = [app beginBackgroundTaskWithName:@"watchAppRequest" expirationHandler:^{

        [[UIApplication sharedApplication] endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;

    }];

//make your calls here to your tasks, when finished, send the reply then terminate the background task

//send reply back to watch
reply(replyInfo);

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [app endBackgroundTask:bgTask];
        bgTask=UIBackgroundTaskInvalid;
    });
}
rmp
  • 3,503
  • 1
  • 17
  • 26