Performing your app actions with Siri through App Shortcuts Provider

Performing your app actions with Siri through App Shortcuts Provider

Expose your app actions to Siri Make with the App Intents framework.

App Intents are responsible for handling actions and objects on which those will be performed.

The true value of creating intents stands in their ability to be performed by Siri on the user's behalf. By integrating Siri with the app’s intents, developers enable a hands-free, natural language experience that lets users trigger actions simply by speaking.

Think of voice-only scenarios:

  • When cooking or cleaning and your hands are messy or busy, speaking to Siri can help set timers or look up recipes.
  • When multitasking, such as carrying items or attending a meeting, voice-only interactions provide a seamless way to get things done.

Starter Project

We will use the following project to explore how to invoke an intent by speaking to Siri.

This is a books library sample app that allows you to keep track of the books you have on your bookshelf.

This starter project contains:

  • View folder:
    • BooksListView - shows the stored books as a list
    • BookDetailView - presents the details of a stored book
    • AddBookView - handles the addition of a new one
    • WebView - rendering the file
  • Model folder, collecting all the model files
    • Book - defines the book type
    • DataModel - data persisted using SwiftData
  • Manager folder
    • NavigationManager - handles navigation within the app
    • DataManager - handles the data operations
  • The BooksShelfAskSiriStarterApp file - the entry point of the app
  • Intents folder - collecting all intents related files
    • BookEntity - handling the AppEntity for the Book model
    • OpenBookIntent - handling the AppIntent that allows opening a specific book

The NavigationManager and the shared Modelcontainer are initialized at the app entry point. Launch the app and start storing your books; they will be needed to launch and test the intent.

To test if the intent is working as expected, create a shortcut from the Shortcuts app. By the end of the tutorial, you will be able to perform the same tasks by invoking them via vocal commands.

We will create shortcuts that invoke actions via vocal commands so that Siri can perform a specific task on the user’s behalf.

Let’s start.

In the Intents folder, create a new file called ShortcutsProvider.swift.

import AppIntents

struct BookShelfShortcutsProvider: AppShortcutsProvider {

    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: OpenBookIntent(),
            phrases: [
                "Open a book in \(.applicationName)"
            ],
            shortTitle: "Open a book",
            systemImageName: "book"
        )
    }
}
  1. Create a struct called BookShelfShortcutsProvider that conforms to the AppShortcutsProvider protocol. You will be prompted by an error that asks you to add stubs to conform to the protocol. Add them.
  2. Start storing in the appShortcuts property instances of AppShortcut using the init(intent:phrases:shortTitle:systemImageName:) initializer.

The AppShortcut type requires the following properties:

  1. intent - the AppIntent object associated with the AppShortcut.
  2. phrases - a collection of AppShortcutPhrases that enables the intent.
  3. shortTitle - a LocalizedStringResource representing the short title of the AppShortcut.
  4. systemImageName - a String representing an sF Symbol for the AppShortcut.

By running the app on device and asking Siri “Open a book in BooksShelfAsksSiriStarter”, you will be prompted with Siri asking you back which book to open.

0:00
/0:22

Two main things make the user experience of our app a little bit disruptive:

  1. The name of the application is too long, which makes it challenging to prompt Siri quickly with the phrase;
  2. The intent doesn’t include the book title the user wants to open, so it is split into two interactions with Siri.

Let’s address them.

Adding an alternative applicationName to invoke the app

In the Info.plist:

  1. Add a new key, INAlternativeAppNames, and set its type on Array .
  2. Inside this array, add a new Dictionary item.
  3. At Item 0, add two new String entries:
    1. The first one with the key INAlternativeAppName and, as value, the alternative name of the app (Books shelf in our example);
    2. The second one with the key INAlternativeAppNamePronunciationHint and, as value, the pronunciation hint of the alternative name, meaning how it could sound.

For this project, we created two different alternative names.

Setting alternative application names or synonyms to be leveraged when invoking Siri by spoken request is a smart way to enhance the user experience when you have long names for your application.

Since it’s highly suggested to always include the applicationName in the AppShortcutPhrases for spoken requests, using familiar or easier to pronounce names makes the UX smoother.

0:00
/0:34

Perform an intent on an entity in a one step interaction with Siri

import AppIntents

struct BookShelfShortcutsProvider: AppShortcutsProvider {
    
    static var appShortcuts: [AppShortcut]{
        AppShortcut(
            intent: OpenBookIntent(),
            phrases: [
                "Open a book in \(.applicationName)",
                "Open \(\.$target) in \(.applicationName)",
                "Open \(\.$target) book in \(.applicationName)"
            ],
            shortTitle: "Open a book",
            systemImageName: "book"
        )
    }
}

In the AppShortcutsProvider struct implementation, in the collection of phrases add a new one to invoke the intent. Use the \.$target binding - the OpenBookIntent property - to make the system aware that properties of the target entity could be used in the phrase. The system will leverage the EntityStringQuery methods to understand the entity the user refers to.

To keep shortcuts accurate and functional, we need to dynamically refresh the app’s shortcut settings. To do that, we leverage the updateAppShortcutParameters() method that updates the possible parameters based on your app’s stored content.


class DataManager {
    
    ...
    
    static func createNewBook(book: Book) async throws {
        ...
        
        BookShelfShortcutsProvider.updateAppShortcutParameters()
    }
    
    static func deleteBook(book: Book) async throws {
        ...
        
        BookShelfShortcutsProvider.updateAppShortcutParameters()
    }
}

This means that every time we add a new object to our stored data with a related AppEntity we need to update the stored parameters. That’s why we call the method when we create or delete new books to be stored.

0:00
/0:16

Final Result

After following all the previous steps, your app should be integrated with Siri and accessible with the sentences defined in your project configuration file. To properly test it, run the project on your device and use Siri to access the app shortcuts defined.

This tutorial explored integrating Siri with your app’s intents via the App Intents framework and AppShortcutsProvider. By addressing naming challenges and including entity parameters, we streamlined voice interactions into a single, efficient command.

You can download the final version of the project here.

Integrating Siri with your app’s intents simplifies task execution while embracing a more natural language style. The refined shortcut phrases and entity parameters allow users to interact with your app intuitively and effortlessly as if conversing with a friend. This approach delivers a smoother, context-aware experience, making hands-free operation seamless and conversational.