I want to be able to trigger a VoIP call with Siri saying "Call Emily using the Next app", without adding shortcuts.
Emily is a contact I added to my contacts, which holds my own phone number. I test the example app on my daily driver phone, so it has a SIM card for calling.
I don't see a "Emily" in your Contacts.
I don't see an app for that. You'll need to download one. Search the App Store
Note, if you have trouble with changing the Display Name. Select project, change the display name, then click away from the project (to any file) and select the project again. Run the app and the name should update.
Here's the code. It works for "Call Emily using the Next app" if my Display Name is Next. It also works for "Call Emily using the Dog app" if my Display Name is Dog.
The example app is written in SwiftUI code with a minimal setup to test the Siri feature.
TestSiriSimple -> TestSiriSimpleIntents -> IntentHandler:
import Intents
class IntentHandler: INExtension {
override func handler(for intent: INIntent) -> Any {
if intent is INStartCallIntent {
return StartCallIntentHandler()
}
return self
}
}
TestSiriSimple -> Shared -> StartCallIntentHandler:
import Foundation
import Intents
class StartCallIntentHandler: NSObject, INStartCallIntentHandling {
func confirm(intent: INStartCallIntent) async -> INStartCallIntentResponse {
let userActivity = NSUserActivity(activityType: String(describing: INStartCallIntent.self))
return INStartCallIntentResponse(code: .continueInApp, userActivity: userActivity)
}
func handle(intent: INStartCallIntent, completion: @escaping (INStartCallIntentResponse) -> Void) {
let response: INStartCallIntentResponse
defer {
completion(response)
}
let userActivity = NSUserActivity(activityType: String(describing: INStartCallIntent.self))
response = INStartCallIntentResponse(code: .continueInApp, userActivity: userActivity)
completion(response)
}
func resolveContacts(for intent: INStartCallIntent) async -> [INStartCallContactResolutionResult] {
guard let contacts = intent.contacts, contacts.count > 0 else {
return []
}
return [INStartCallContactResolutionResult.success(with: contacts[0])]
}
func resolveCallCapability(for intent: INStartCallIntent) async -> INStartCallCallCapabilityResolutionResult {
INStartCallCallCapabilityResolutionResult(callCapabilityResolutionResult: .success(with: intent.callCapability))
}
func resolveDestinationType(for intent: INStartCallIntent) async -> INCallDestinationTypeResolutionResult {
INCallDestinationTypeResolutionResult.success(with: .normal)
}
}
The root app class is unchanged. TestSiriSimple -> Shared -> ContentView:
import SwiftUI
import Intents
struct ContentView: View {
@State private var status: INSiriAuthorizationStatus = .notDetermined
var body: some View {
Text("Hello, world! Siri status: \(status.readableDescription)")
.padding()
.onAppear {
requestSiri()
}
.onContinueUserActivity(NSStringFromClass(INStartCallIntent.self)) { userActivity in
continueUserActivity(userActivity)
}
}
private func requestSiri() {
INPreferences.requestSiriAuthorization { status in
self.status = status
}
}
private func continueUserActivity(_ userActivity: NSUserActivity) {
if let intent = userActivity.interaction?.intent as? INStartCallIntent {
// Find person from contacts or create INPerson from app specific contacts.
// Execute VoIP code.
// I consider it a success if Siri responds with "Calling Now", opens the app and reaches this code.
}
}
}
extension INSiriAuthorizationStatus {
var readableDescription: String {
switch self {
case .authorized:
return "Authorized"
case .denied:
return "Denied"
case .notDetermined:
return "Not determined"
case .restricted:
return "Restricted"
default:
return "Unknown"
}
}
}
TestSiriSimple -> (Main) Info.plist
TestSiriSimpleIntents -> Info.plist
Privacy - Siri Usage Description = Siri wants to let you start calls in this app.
TestSiriSimpleIntents target has INStartCallIntent as a supported intent
If you have any ideas, they are more than welcome!
I'm willing to share a zip of my example code if you could show me how I would go about that in StackOverflow. If any other other info would help, don't hesitate to comment!
There's a better phrase than Call Emily using the Nexxt app
, try the following:
Call Emily on Nexxt
See documentation: https://developer.apple.com/documentation/sirikit/instartaudiocallintent