iosiphoneswiftsirikitintents-extension

Siri always responds 'Continue in the app' when starting workout with SiriKit


I was working on a SiriKit intents extension for our app. We're using the workout extension type. The problem is, I just put the required methods in and always pass .ready but Siri always responds,

Sorry, you'll have to continue in the app.

I have tried other responses as well (.failure and .unspecified), but she still says to continue in the app. I've followed the documentation provided by Apple to setup my .plist files, but it still might be something related to that.

Here is my Intents code :

class IntentHandler: INExtension, INStartWorkoutIntentHandling, INPauseWorkoutIntentHandling, INResumeWorkoutIntentHandling, INCancelWorkoutIntentHandling, INEndWorkoutIntentHandling {


override func handler(for intent: INIntent) -> Any {
    // This is the default implementation.  If you want different objects to handle different intents,
    // you can override this and return the handler you want for that particular intent.

    return self
}

func handle(startWorkout intent: INStartWorkoutIntent, completion: @escaping (INStartWorkoutIntentResponse) -> Void) {
    print("Starting Service")
    let activity = NSUserActivity(activityType: "start_service")
    let result = INStartWorkoutIntentResponse(code: .ready, userActivity: activity)
    completion(result)
}

func handle(endWorkout intent: INEndWorkoutIntent, completion: @escaping (INEndWorkoutIntentResponse) -> Void) {
    print("Ending Service")
    let result = INEndWorkoutIntentResponse(code: .ready, userActivity: nil)
    completion(result)
}

func handle(pauseWorkout intent: INPauseWorkoutIntent, completion: @escaping (INPauseWorkoutIntentResponse) -> Void) {
    print("Pausing Service")
    let result = INPauseWorkoutIntentResponse(code: .ready, userActivity: nil)
    completion(result)
}

func handle(cancelWorkout intent: INCancelWorkoutIntent, completion: @escaping (INCancelWorkoutIntentResponse) -> Void) {
    print("Cancel Service")
    let result = INCancelWorkoutIntentResponse(code: .ready, userActivity: nil)
    completion(result)
}

func handle(resumeWorkout intent: INResumeWorkoutIntent, completion: @escaping (INResumeWorkoutIntentResponse) -> Void) {
    print("Resume Service")
    let result = INResumeWorkoutIntentResponse(code: .ready, userActivity: nil)
    completion(result)
}
}

I tried a breakpoint where the start workout intent is handled, and it does hit the function. I also tried passing .ready to a INMessageIntent and Siri responded without saying open in the app. I'm wondering if this is always the case for workout extensions. If it is, I would still like Siri to show my IntentsUI.

Thanks for the responses.


Solution

  • Once you are ready to start the workout in your app, you need to call the completion handler with .continueInApp

    So that would be something like:

    public func handle(startWorkout intent: INStartWorkoutIntent, completion: @escaping (INStartWorkoutIntentResponse) -> Swift.Void) {
        let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartWorkoutIntent.self))
        let response = INStartWorkoutIntentResponse(code: .continueInApp, userActivity: userActivity)
        completion(response)
    }
    

    See the documentation:

    Your extension is ready to transfer control to the app so that the workout can be started. Upon returning this code, SiriKit launches your app and passes it the NSUserActivity object you provided at initialization time. (If you did not provide a user activity object, SiriKit creates one for you.) SiriKit adds an INInteraction object with the intent and your response to the user activity object before delivering it. Your app should use the information in the user activity object to start the workout.