Search code examples
iosswiftsirisirikitsirishortcuts

Facing issue in Siri Integration with custom intents


I’m trying to integrate Siri Shortcuts to my application. The concept which I’m trying is to get reward points of my card with secret pin confirmation. Please find what I have done for this below.

  1. Enabled Siri in capabilities and added Siri Intent definition file.
  2. Added new custom intent named say Rewards.

  3. Defined the title. Subtitle and params(accType, pin) with confirmation enabled. Pin will be sent separately to user.

enter image description here

  1. Then defined the intent response with param ‘rewardPoints’ and defined the response messages.

enter image description here

  1. Added Siri intent extensions.
  2. Added custom intent to info.plist files within project and intent extension.

enter image description here

enter image description here

  1. Verified and added new handler for the custom intent and define the resolve, handle and confirm methods as below. For now, I’m returning random no for reward points.
//
//  RewardsIntentHandler.swift
//  SiriIntentExt
//

import UIKit
import Intents

class RewardsIntentHandler: NSObject, RewardsIntentHandling {

    func resolveAccType(for intent:RewardsIntent, with completion: @escaping ([INStringResolutionResult]) -> Void) {
        guard let accType = intent.accType else {
            completion([INStringResolutionResult.needsValue()])
            return
        }

        completion([INStringResolutionResult.success(with: accType)])
    }

    func resolvePin(for intent:RewardsIntent, with completion: @escaping ([INIntegerResolutionResult]) -> Void) {

        guard let verifyPin = intent.pin else {
            completion([INIntegerResolutionResult.needsValue()])
            return
        }

        completion([INIntegerResolutionResult.confirmationRequired(with: verifyPin as? Int)])
    }

    func confirm(intent: RewardsIntent, completion: @escaping (RewardsIntentResponse) -> Void) {
        completion(RewardsIntentResponse.init(code: RewardsIntentResponseCode.ready, userActivity: nil))
    }

    func handle(intent: RewardsIntent, completion: @escaping (RewardsIntentResponse) -> Void) {

        guard intent.accType != nil else {
            completion(RewardsIntentResponse.init(code: RewardsIntentResponseCode.continueInApp, userActivity: nil))
            return
        }

        guard intent.pin != nil else {
            completion(RewardsIntentResponse.init(code: RewardsIntentResponseCode.continueInApp, userActivity: nil))
            return
        }

        let response = RewardsIntentResponse.success(rewardPoints: NSNumber(value: 3453))
        completion(response)
    }
}
  1. Modified the IntentHandler to return rewards handler for rewards intent
//
//  IntentHandler.swift
//  SiriIntentExt
//

import Intents

class IntentHandler: INExtension {

    override func handler(for intent: INIntent) -> Any {

        if intent is RewardsIntent {
            return RewardsIntentHandler()
        }

        return self
    }

}
  1. Donated the intent on view load as below.
//
//  ViewController.swift
//  Shortcuts
//

import UIKit
import Intents

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        siriAuthorisarion()
        donateRewardIntent()
    }

    func siriAuthorisarion()  {

        INPreferences.requestSiriAuthorization { (status) in
            print("Siri Authorization Status - ", status)
        }
    }

    func donateRewardIntent() {

        let rewardsIntent = RewardsIntent()
        rewardsIntent.suggestedInvocationPhrase = "Reward Points"
        rewardsIntent.accType = "test account"

        let interaction = INInteraction(intent: rewardsIntent, response: nil)

        interaction.donate { error in
            if let error = error {
                print("Donating intent failed with error \(error)")
            }

            DispatchQueue.main.async {
                let alert = UIAlertController.init(title: ((error != nil) ? "Error" : "Success"), message: ((error != nil) ? "Oops!!! Error occured on donating intent." : "Intent donated succussfully!!!"), preferredStyle: .alert)
                alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }
        }
    }
}

I'm facing problem from the above code base. Siri is not requesting for pin and not able to get the exact reward points for the account.

Have following questions.

  1. Can we add the intents programmatically to Siri instead adding from shortcuts app or settings. So that user can directly use the functionality once installing the application.
  2. Once intent is added using Shortcuts app, I’m trying the ask Siri for reward points. Its immediately requesting for my app shortcuts defined. Once we say 'yes' to request, I need to be asked for pin. But Siri replies with some problem with my app. What to be done for asking for next param value.
  3. In the handler file, I have added the resolve methods for each parameters. I feel, resolve methods are not getting called to validate the values. Do we need to handle anything to make resolve methods work?
  4. How can I debug the handler implementation using breakpoint within resolve/handle/confirm methods.

Thanks in advance.


Solution

  • Find my analysis for the above questions.

    1. Can we add the intents programmatically to Siri instead adding from shortcuts app or settings. So that user can directly use the functionality once installing the application.

    By default, intents are provided for specific domains such as messaging, payments, photos, workout, etc. No need to explicitly add intents through shortcuts for theses specific domains. Apart from these domains if we are creating custom intent, we are in need to donate and add the intents to Siri using shortcut/settings application.

    1. Once intent is added using Shortcuts app, I’m trying the ask Siri for reward points. Its immediately requesting for my app shortcuts defined. Once we say 'yes' to request, I need to be asked for pin. But Siri replies with some problem with my app. What to be done for asking for next param value.

    From iOS13, Apple has added Siri parameters and Siri suggestion for custom intents to request the missing parameters. Till iOS12, we don't have parameters option for custom intents.

    1. In the handler file, I have added the resolve methods for each parameters. I feel, resolve methods are not getting called to validate the values. Do we need to handle anything to make resolve methods work?

    In iOS12, we cannot add resolve methods for parameters in custom intents. Resolve methods handled only for specific domains provided within Intents extensions as mentioned in question 1. From iOS13, we can have resolve methods for custom intents based on the parameters.

    1. How can I debug the handler implementation using breakpoint within resolve/handle/confirm methods.

    We can add breakpoints and debug intent handler methods.

    Thanks.