Siri shortcuts with custom intent utilizing WCSession

Viewed 359

Our app also contains a Watch Extension. Part of the apps functionality is to start or stop a process on either device and inform its counterpart by sending the event along with the date it occured. We now would also like to use Siri shortcuts with custom intents for this. At the moment we don't have a watch running watchOS 5 so we can only test this in the simulator.

Following Apples SoupChef example app, we managed to get the shortcuts running on both devices performing their task in the background as wanted. However activating a WCSession for sending the message to the other device fails with error

[WC] -[WCXPCManager onqueue_reconnect]_block_invoke error reconnecting to daemon due to NSXPCConnectionInterrupted

being repeatedly called.

Before attempting to send the message to the other device in the IntentHandler's

func handle(intent: OurIntent, completion: @escaping (OurIntentResponse) -> Void)

We are trying to activate the session a the very beginning of the its

func confirm(intent: OurIntent, completion: @escaping (OurIntentResponse) -> Void) {
    let _ = Communicator.sharedInstance

    // ...
}

Communicator is implemented as a singleton, trying to activate the session in its intit method like so:

if WCSession.isSupported() {
  let session = WCSession.default
  session.delegate = self
  session.activate() // fails with error mentioned above
}

We are aware of the limitaions about available APIs in App Extensions as mentioned in Apple documentation but this seems not be the case here, because we get passed WCSession.isSupported().

Running the shortcuts not in the background but having them open the app would of course solve the problem, but this would make shortcuts pretty useless in our case.

Does anyone know if we miss any prerequisites to use WCSession here or is it simply not possible? Like said before we can only test in the simulator at the moment. Could this be the problem?

Any help is much appreciated

1 Answers

Due to changed priorities we only recently continued with the Siri shortcuts. Because we didn't find a solution to our problem but instead also encountered a problem with our custom IntentResponses we decided to handle all logic in our app / watchExtension. So now in our IntentHandler's handle method we simply pass .continueInApp to the completion block. This will then bring the app to the foreground where the now implemented optional delegate method gets called.

func application(_ application: UIApplication,
             continue userActivity: NSUserActivity,
             restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

    if let intent = userActivity.interaction?.intent {
    // make desired viewController frontmost
    // ...

        if intent is OurStartIntent {
            // check state and send message to watch
        }

        else if intent is OurStopIntent {
            // check state and send message to watch
        }
    }
// ...

The equivalent method for the watch ExtensionDelegate is

func handle(_ userActivity: NSUserActivity)

Identifying the intent we first check if the app is in a state to handle the intent, e.g. the process not already running when a StartIntent was used. This was formerly the task we intended for the IntentHandler's confirm method and we implemented custom IntentResponses for those cases. However this only works well if the user taps on suggested shortcuts, receiving an explanation why this intent can not be handled. For spoken shortcuts our IntentResponses were ignored. Siris answer then always was: "Sorry, there was a problem with the app". Another though in our case minor problem is that above mentioned watch ExtensionDelegate method for some reason always gets called twice. Also described here together with a possible solution by passing a timestamp.

I hope this might help someone.

Thorsten

Related