12

I know that the openParentApplication api in watch kit extension can open the host app in the background but not in the foreground.

I also tried using openUrl() api of NSExtensionContext as below:

NSExtensionContext *ctx = [[NSExtensionContext alloc] init];

NSURL *url = [NSURL URLWithString:@"myScheme://today"];
[ctx openURL:url completionHandler:^(BOOL success) {
    NSLog(@"fun=%s after completion. success=%d", __func__, success);
}];
[ctx completeRequestReturningItems:ctx.inputItems completionHandler:nil];

Here too the host app is not launched. Am I missing something? or is it not possible to launch the host app from watch kit extension?

Ashish Kakkad
  • 23,586
  • 12
  • 103
  • 136
Ganesh Nayak
  • 802
  • 11
  • 38

3 Answers3

22

As of Beta 3 of iOS 8.2 it is currently not possible to open iOS app to foreground. As you said openParentApplication can open app in background. Unfortunately there is no sign of API to open app on iPhone.

Multiple posts on Apple Dev Forums mentioned that it's not possible

https://devforums.apple.com/message/1076125#1076125

Correct, a notification can still declare a background action that the iPhone app will handle, so in that sense it can launch the iPhone app. But the iPhone app cannot be brought to the foreground by a WatchKit app.

And other post

https://devforums.apple.com/message/1082620#1082620

On a device, it[Watch app] will not - bring your iOS app to the foreground.

lvp
  • 2,078
  • 18
  • 24
12

I'm hopeful that Apple will provide API for launching the parent app from a watch app in a future beta, but for now I've managed to achieve it by doing the following...

Call openParentApplication:reply: as normal:

- (void)openPhoneApp {
    [WKInterfaceController openParentApplication:[NSDictionary new] reply:nil];
}

Implement application:handleWatchKitExtensionRequest:reply: in your AppDelegate, and launch itself using a custom URL scheme:

- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"myappscheme://open"]];
}
JTaylor
  • 121
  • 3
  • Excellent suggestion. I tried the same code from extensions but was not supported there. Will the app be approved?? Is this legal? – Ganesh Nayak Feb 04 '15 at 11:24
  • I'm not sure whether Apple would approve this. I can't see why not because as far as I can tell it doesn't break any rules. This is only a temporary workaround anyway, I'm hoping that Apple will provide an official way to do this in a future beta. – JTaylor Feb 07 '15 at 18:38
  • 9
    While this approach does launch the parent iOS app in the foreground in the simulator, I have verified with Apple twice that this functionality will not be allowed in the App Store. This answer is not correct and should not be used. @Ivp has the correct answer here. – cnoon Mar 15 '15 at 17:00
  • @cnoon won't it be allowed even from a WatchKit app? Is there an alternative way? – AppsDev Mar 20 '15 at 08:24
9

If you need to open your parent app in the foreground, use Handoff!

https://developer.apple.com/handoff/

Example:

Somewhere shared for both:

static let sharedUserActivityType = "com.yourcompany.yourapp.youraction"
static let sharedIdentifierKey = "identifier"

on your Watch:

updateUserActivity(sharedUserActivityType, userInfo: [sharedIdentifierKey : 123456], webpageURL: nil)

on your iPhone in App Delegate:

func application(application: UIApplication, willContinueUserActivityWithType userActivityType: String) -> Bool {
    if (userActivityType == sharedUserActivityType) {
        return true
    }
    return false
}

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]!) -> Void) -> Bool {
    if (userActivity.activityType == sharedUserActivityType) {
        if let userInfo = userActivity.userInfo as? [String : AnyObject] {
            if let identifier = userInfo[sharedIdentifierKey] as? Int {
                //Do something
                let alert = UIAlertView(title: "Handoff", message: "Handoff has been triggered for identifier \(identifier)" , delegate: nil, cancelButtonTitle: "Thanks for the info!")
                alert.show()
                return true
            }
        }
    }
    return false
}

And finally (this step is important!!!): In your Info.plist(s)

enter image description here

stk
  • 6,311
  • 11
  • 42
  • 58