Partager via


Raccourcis Siri dans Xamarin.iOS

Dans iOS 10, Apple a introduit SiriKit, ce qui permet de créer des messages, des appels VoIP, des paiements, des séances d’entraînement, des réservations de course et des applications de recherche de photos qui interagissent avec Siri.

Dans iOS 11, SiriKit a pris en charge davantage de types d’applications et une plus grande flexibilité pour la personnalisation de l’interface utilisateur.

iOS 12 ajoute des raccourcis Siri, ce qui permet à tous les types d’applications d’exposer leurs fonctionnalités à Siri. Siri apprend quand certaines tâches basées sur l’application sont les plus pertinentes pour l’utilisateur et utilise ces connaissances pour suggérer des actions potentielles via des raccourcis. Le fait d’appuyer sur un raccourci ou de l’appeler avec une commande vocale ouvre une application ou exécute une tâche en arrière-plan.

Les raccourcis doivent être utilisés pour accélérer la capacité d’un utilisateur à accomplir une tâche commune , dans de nombreux cas, sans même ouvrir l’application en question.

Exemple d’application : Soup Chef

Pour mieux comprendre les raccourcis Siri, consultez l’exemple d’application Soup Chef. Soup Chef permet aux utilisateurs de passer des commandes à partir d’un restaurant de soupe imaginaire, d’afficher leur historique des commandes et de définir des expressions à utiliser lors de la commande de soupe en interagissant avec Siri.

Conseil

Avant de tester Soup Chef sur un simulateur ou un appareil iOS 12, activez les deux paramètres suivants, qui sont utiles lors du débogage des raccourcis :

  • Dans l’application Paramètres, activez les raccourcis récents pour les développeurs>.
  • Dans l’application Paramètres, activez les dons d’affichage des développeurs > sur l’écran de verrouillage.

Ces paramètres de débogage facilitent la recherche de raccourcis récemment créés (au lieu de prédire) sur l’écran de verrouillage iOS et l’écran de recherche.

Pour utiliser l’exemple d’application :

  • Installez et exécutez l’exemple d’application Soup Chef sur un simulateur ou un appareil iOS 12.
  • Cliquez sur le + bouton dans le coin supérieur droit pour créer un ordre.
  • Sélectionnez un type de soupe, spécifiez une quantité et des options, puis appuyez sur Passer une commande.
  • Dans l’écran Historique des commandes, appuyez sur l’ordre nouvellement créé pour afficher ses détails.
  • En bas de l’écran détails de la commande, appuyez sur Ajouter à Siri.
  • Enregistrez une expression vocale à associer à l’ordre et appuyez sur Terminé.
  • Réduisez le chef de soupe, appelez Siri et réécrire la commande à l’aide de l’expression vocale que vous avez enregistrée.
  • Une fois que Siri a terminé la commande, rouvrez le Chef de soupe et notez que la nouvelle commande est répertoriée sur l’écran Historique des commandes.

L’exemple d’application montre comment :

Info.plist et Entitlements.plist

Avant de creuser plus profondément dans le code Soup Chef, examinez ses fichiers Info.plist et Entitlements.plist .

Info.plist

Le fichier Info.plist dans le projet SoupChef définit l’identificateurde bundle comme com.xamarin.SoupChef. Cet identificateur de bundle sera utilisé comme préfixe pour les identificateurs de bundle des extensions d’interface utilisateur Intentions et Intentions décrites plus loin dans ce document.

Le fichier Info.plist contient également l’entrée suivante :

<key>NSUserActivityTypes</key>
<array>
    <string>OrderSoupIntent</string>
    <string>com.xamarin.SoupChef.viewMenu</string>
</array>

Cette NSUserActivityTypes paire clé/valeur indique que Soup Chef sait gérer un OrderSoupIntent, et NSUserActivity avoir un ActivityType « com.xamarin.SoupChef.viewMenu ».

Les activités et les intentions personnalisées passées à l’application elle-même, par opposition à ses extensions, sont gérées dans le AppDelegate (par UIApplicationDelegate la ContinueUserActivity méthode).

Entitlements.plist

Le fichier Entitlements.plist du projet SoupChef contient les entrées suivantes :

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.xamarin.SoupChef</string>
</array>
<key>com.apple.developer.siri</key>
<true/>

Cette configuration indique que l’application utilise le groupe d’applications « group.com.xamarin.SoupChef ». L’extension d’application SoupChefIntents utilise ce même groupe d’applications, ce qui permet aux deux projets de partager Données NSUserDefaults.

La com.apple.developer.siri clé indique que l’application interagit avec Siri.

Remarque

La configuration de build du projet SoupChef définit les droits personnalisés sur Entitlements.plist.

Utilisation d’un raccourci NSUserActivity pour ouvrir une application

Pour créer un raccourci qui ouvre une application pour afficher du contenu spécifique, créez-la NSUserActivity et attachez-la au contrôleur de vue pour l’écran que vous souhaitez ouvrir.

Configuration d’un NSUserActivity

Dans l’écran du menu, SoupMenuViewController crée un NSUserActivity élément et l’affecte à la propriété du contrôleur d’affichage UserActivity :

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    UserActivity = NSUserActivityHelper.ViewMenuActivity;
}

La définition de la UserActivity propriété donne l’activité à Siri. À partir de ce don, Siri obtient des informations sur le moment et l’endroit où cette activité est pertinente pour l’utilisateur et apprend à mieux le suggérer à l’avenir.

NSUserActivityHelper est une classe utilitaire incluse dans la solution SoupChef , dans la bibliothèque de classes SoupKit . Il crée une NSUserActivity propriété et définit différentes propriétés liées à Siri et à la recherche :

public static string ViewMenuActivityType = "com.xamarin.SoupChef.viewMenu";

public static NSUserActivity ViewMenuActivity {
    get
    {
        var userActivity = new NSUserActivity(ViewMenuActivityType)
        {
            Title = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_TITLE", "View menu activity title"),
            EligibleForSearch = true,
            EligibleForPrediction = true
        };

        var attributes = new CSSearchableItemAttributeSet(NSUserActivityHelper.SearchableItemContentType)
        {
            ThumbnailData = UIImage.FromBundle("tomato").AsPNG(),
            Keywords = ViewMenuSearchableKeywords,
            DisplayName = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_TITLE", "View menu activity title"),
            ContentDescription = NSBundleHelper.SoupKitBundle.GetLocalizedString("VIEW_MENU_CONTENT_DESCRIPTION", "View menu content description")
        };
        userActivity.ContentAttributeSet = attributes;

        var phrase = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_SUGGESTED_PHRASE", "Voice shortcut suggested phrase");
        userActivity.SuggestedInvocationPhrase = phrase;
        return userActivity;
    }
}

Notez les fonctionnalités suivantes en particulier :

  • Paramètre EligibleForPrediction pour true indiquer que Siri peut prédire cette activité et la faire apparaître en tant que raccourci.
  • Le ContentAttributeSet tableau est un standard CSSearchableItemAttributeSet utilisé pour inclure des NSUserActivity résultats de recherche iOS.
  • SuggestedInvocationPhrase est une expression que Siri suggère à l’utilisateur comme choix potentiel lors de l’affectation d’une expression à un raccourci.

Gestion d’un raccourci NSUserActivity

Pour gérer un NSUserActivity raccourci appelé par un utilisateur, une application iOS doit remplacer la ContinueUserActivity méthode de la AppDelegate classe, en répondant en fonction du ActivityType champ de l’objet passé NSUserActivity :

public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
    // ...
    else if (userActivity.ActivityType == NSUserActivityHelper.ViewMenuActivityType)
    {
        HandleUserActivity();
        return true;
    }
    // ...
}

Cette méthode appelle HandleUserActivity, qui recherche le segue à l’écran de menu et l’appelle :

void HandleUserActivity()
{
    var rootViewController = Window?.RootViewController as UINavigationController;
    var orderHistoryViewController = rootViewController?.ViewControllers?.FirstOrDefault() as OrderHistoryTableViewController;
    if (orderHistoryViewController is null)
    {
        Console.WriteLine("Failed to access OrderHistoryTableViewController.");
        return;
    }
    var segue = OrderHistoryTableViewController.SegueIdentifiers.SoupMenu;
    orderHistoryViewController.PerformSegue(segue, null);
}

Affectation d’une expression à un NSUserActivity

Pour affecter une expression à une NSUserActivityapplication iOS Paramètres, ouvrez l’application iOS et choisissez Siri &Search > My Shortcuts. Sélectionnez ensuite le raccourci (dans ce cas, « Commander le déjeuner ») et enregistrez une expression.

L’appel de Siri et l’utilisation de cette expression ouvre soup Chef à l’écran de menu.

Utilisation d’un raccourci d’intention personnalisé pour effectuer une tâche

Définition d’une intention personnalisée

Pour fournir un raccourci qui permet à un utilisateur d’effectuer rapidement une tâche spécifique liée à votre application, créez une intention personnalisée. Une intention personnalisée représente une tâche qu’un utilisateur peut souhaiter terminer, des paramètres pertinents pour cette tâche et des réponses potentielles résultant de l’exécution de la tâche. Selon la façon dont une intention personnalisée est définie, l’appel peut ouvrir votre application ou exécuter une tâche en arrière-plan.

Utilisez Xcode 10 pour créer des intentions personnalisées. Dans le référentiel SoupChef, l’intention personnalisée est définie dans OrderSoupIntentCodeGen, un Objective-C projet. Ouvrez ce projet et sélectionnez le fichier Intents.intentdefinition dans le navigateur de projet pour afficher l’intention OrderSoup.

Notez les caractéristiques suivantes :

  • L’intention a une catégorie de commande. Il existe différentes catégories prédéfinies qui peuvent être utilisées pour les intentions personnalisées ; sélectionnez celui qui correspond le plus étroitement à la tâche que votre intention personnalisée active. Étant donné que cette solution est une application de commande de soupe, OrderSoupIntent utilise Order.
  • La boîte de réception de confirmation case activée indique si Siri doit demander une confirmation avant d’exécuter la tâche. Pour l’intention commande soupe dans Soup Chef, cette option est activée car l’utilisateur effectue un achat.
  • La section Parameters du fichier .intentdefinition définit les paramètres pertinents pour un raccourci. Pour passer une commande de soupe, le Chef de soupe doit connaître le type de soupe, sa quantité et toutes les options associées. Chaque paramètre a un type ; paramètre qui ne peut pas être représenté par un type prédéfini est défini en tant que personnalisé.
  • L’interface Types de raccourcis décrit les différentes combinaisons de paramètres que Siri peut utiliser lors de la suggestion de votre raccourci. Les sections Titre et Sous-titre associées vous permettent de définir les messages que Siri utilisera lors de la présentation d’un raccourci suggéré à l’utilisateur.
  • La boîte de dialogue Prise en charge de l’exécution en arrière-plan case activée box doit être sélectionnée pour tout raccourci qui peut être exécuté sans ouvrir l’application pour une interaction utilisateur supplémentaire.

Définition des réponses d’intention personnalisées

L’élément Réponse imbriqué sous l’intention OrderSoup représente les réponses potentielles résultant d’une commande de soupe.

Dans la définition de réponse de l’intention OrderSoup , notez les fonctionnalités suivantes :

  • Les propriétés d’une réponse peuvent être utilisées pour personnaliser le message communiqué à l’utilisateur. La réponse de l’intention OrderSoup a des propriétés de soupe et waitTime .
  • Les modèles de réponse spécifient les différents messages de réussite et d’échec qui peuvent être utilisés pour indiquer l’état une fois la tâche d’une intention terminée.
  • La boîte de réception Réussite case activée doit être sélectionnée pour les réponses qui indiquent la réussite.
  • La réponse de réussite OrderSoupIntent utilise les propriétés soupe et waitTime pour fournir un message convivial et utile décrivant quand l’ordre de soupe sera prêt.

Génération de code pour l’intention personnalisée

La création du projet Xcode contenant cette définition d’intention personnalisée entraîne la génération de code Xcode qui peut être utilisé pour interagir par programmation avec l’intention personnalisée et ses réponses.

Pour afficher ce code généré :

  • Ouvrez AppDelegate.m.
  • Ajoutez une importation au fichier d’en-tête de l’intention personnalisée : #import "OrderSoupIntent.h"
  • Dans n’importe quelle méthode de la classe, ajoutez une référence à OrderSoupIntent.
  • Cliquez avec le bouton droit sur OrderSoupIntent et choisissez Accéder à la définition.
  • Cliquez avec le bouton droit dans le fichier nouvellement ouvert, OrderSoupIntent.h, puis sélectionnez Afficher dans Finder.
  • Cette action ouvre une fenêtre Finder qui contient un fichier .h et .m contenant le code généré.

Ce code généré inclut les éléments suivants :

  • OrderSoupIntent : classe qui représente l’intention personnalisée.
  • OrderSoupIntentHandling : protocole qui définit les méthodes qui seront utilisées pour confirmer que l’intention doit être exécutée et la méthode qui l’exécute réellement.
  • OrderSoupIntentResponseCode – Énumération qui définit différents états de réponse.
  • OrderSoupIntentResponse : classe qui représente la réponse à l’exécution d’une intention.

Création d’une liaison à l’intention personnalisée

Pour utiliser le code généré par Xcode dans une application Xamarin.iOS, créez une liaison C# pour celle-ci.

Création d’une bibliothèque statique et de définitions de liaison C#

Dans le référentiel SoupChef, examinez le dossier OrderSoupIntentStaticLib , puis ouvrez le projet OrderSoupIntentStaticLib.xcodeproj Xcode.

Ce projet de bibliothèque statique Cocoa Touch contient les fichiers OrderSoupIntent.h et OrderSoupIntent.m générés par Xcode.

Configuration des paramètres de génération du projet de bibliothèque statique

Dans le navigateur de projet Xcode, sélectionnez le projet de niveau supérieur, OrderSoupIntentStaticLib, puis accédez aux sources de compilation des phases > de génération. Notez que OrderSoupIntent.m (qui importe OrderSoupIntent.h) est répertorié ici. Dans Lier des fichiers binaires avec des bibliothèques, notez que Intents.framework et Foundation.framework sont inclus. Avec ces paramètres en place, l’infrastructure sera générée correctement.

Génération de la bibliothèque statique et génération de définitions de liaisons C#

Pour générer la bibliothèque statique et générer des définitions de liaisons C#, procédez comme suit :

  • Installez Objective Sharpie, l’outil utilisé pour générer des définitions de liaisons à partir des fichiers .h et .m créés par Xcode.

  • Configurez votre système pour utiliser les outils en ligne de commande Xcode 10 :

    Avertissement

    La mise à jour des outils en ligne de commande sélectionné a un impact sur toutes les versions installées de Xcode sur votre système. Lorsque vous avez terminé d’utiliser l’exemple d’application Soup Chef, veillez à rétablir ce paramètre à sa configuration d’origine.

    • Dans Xcode, choisissez emplacements des préférences > Xcode > et définissez les outils en ligne de commande sur l’installation Xcode 10 la plus actuelle disponible sur votre système.
  • Dans le terminal, cd accédez au répertoire OrderSoupIntentStaticLib .

  • Type make, qui génère :

    • Bibliothèque statique, libOrderSoupIntentStaticLib.a
    • Dans le répertoire de sortie bo , définitions de liaisons C# :
      • ApiDefinitions.cs
      • StructsAndEnums.cs

Le projet OrderSoupIntentBindings , qui s’appuie sur cette bibliothèque statique et ses définitions de liaisons associées, génère automatiquement ces éléments. Toutefois, l’exécution manuelle du processus ci-dessus garantit qu’elle est générée comme prévu.

Pour plus d’informations sur la création d’une bibliothèque statique et l’utilisation d’Objective Sharpie pour créer des définitions de liaisons C#, consultez la procédure pas à pas de liaison d’une bibliothèque iOSObjective-C.

Création d’une bibliothèque de liaisons

Avec la bibliothèque statique et les définitions de liaisons C# créées, la partie restante nécessaire pour consommer le code lié à l’intention généré par Xcode dans un projet Xamarin.iOS est une bibliothèque de liaisons.

Dans le référentiel Soup Chef, ouvrez le fichier SoupChef.sln . Entre autres choses, cette solution contient OrderSoupIntentBinding, une bibliothèque de liaisons pour la bibliothèque statique générée précédemment.

Notez en particulier que ce projet inclut :

  • ApiDefinitions.cs : fichier généré précédemment par Objective Sharpie et ajouté à ce projet. L’action de génération de ce fichier est définie sur ObjcBindingApiDefinition.

  • StructsAndEnums.cs : un autre fichier généré précédemment par Objective Sharpie et ajouté à ce projet. L’action de génération de ce fichier est définie sur ObjcBindingCoreSource.

  • Référence native à libOrderSoupIntentStaticLib.a, la bibliothèque statique créée précédemment. Mettez à jour les propriétés de référence natives et spécifiez les valeurs suivantes :

    1. Frameworks = Foundation Intents
    2. Smart Link = On
    3. Forcer la charge = On
    4. Kind = Static

Remarque

Les deux ApiDefinitions.cs et StructsAndEnums.cs contiennent des attributs tels que [Watch (5,0), iOS (12,0)]. Ces attributs, générés par Objective Sharpie, ont été commentés, car ils ne sont pas nécessaires pour ce projet.

Pour plus d’informations sur la création d’une bibliothèque de liaisons C#, consultez la procédure pas à pas de liaison d’une bibliothèque iOSObjective-C.

Notez que le projet SoupChef contient une référence à OrderSoupIntentBinding, ce qui signifie qu’il peut désormais accéder, en C#, aux classes, interfaces et énumérations qu’il contient :

  • OrderSoupIntent
  • OrderSoupIntentHandling
  • OrderSoupIntentResponse
  • OrderSoupIntenseResponseCode

Création d’une infrastructure Swift

Le code natif de définition d’intention est généré par Xcode par défaut à l’aide du langage de votre projet natif. Si vous définissez le fichier Intents.intentdefinition dans un projet Swift, Xcode vous génère un fichier Swift unique avec toutes les classes requises, que vous pouvez utiliser pour créer une infrastructure Swift.

Conseil

Vous pouvez sélectionner une langue souhaitée pour le code d’intention généré dans les paramètres de génération Xcode. Accédez à Build cible > intention Paramètres > compilateur de définition d’intention - Génération de code, puis sélectionnez Swift ou Objective-C. Vous pouvez également le conserver automatiquement pour qu’il corresponde à votre langue cible.

Le processus de création d’une infrastructure Swift est similaire à celui décrit précédemment :

  1. Créez un projet de framework Swift.
  2. Copiez le fichier Swift généré automatiquement avec le code d’intention dans ce projet, vous trouverez ce fichier comme décrit ici.
  3. Activez l’en-tête Objective-C de pontage, de sorte que l’infrastructure est générée automatiquement avec le fichier d’en-tête sharpie requisObjective-C.

Une fois l’infrastructure générée, suivez les mêmes étapes décrites précédemment pour créer une liaison Xamarin. Vous pouvez en savoir plus sur la création d’une liaison pour une infrastructure Swift ici.

Ajout du fichier de définition d’intention à votre solution

Dans la solution C# SoupChef , le projet SoupKit contient du code partagé entre l’application et ses extensions. Le fichier Intents.intentdefinition a été placé dans le répertoire Base.lproj de SoupKit et a une action de génération de contenu. Le processus de génération copie ce fichier dans le bundle d’applications Soup Chef, où il est nécessaire que l’application fonctionne correctement.

Don d’une intention

Pour que Siri suggère un raccourci, il doit d’abord comprendre quand le raccourci est pertinent.

Pour donner à Siri cette compréhension, Soup Chef donne une intention à Siri chaque fois que l’utilisateur place une commande de soupe. Sur la base de ce don - quand il a été donné, où il a été donné, les paramètres qu’il contient - Siri apprend quand suggérer le raccourci à l’avenir.

SoupChef utilise la SoupOrderDataManager classe pour placer des dons. Lorsqu’elle est appelée pour passer une commande de soupe pour un utilisateur, la PlaceOrder méthode appelle DonateInteractionà son tour :

void DonateInteraction(Order order)
{
    var interaction = new INInteraction(order.Intent, null);
    interaction.Identifier = order.Identifier.ToString();
    interaction.DonateInteraction((error) =>
    {
        // ...
    });
}

Après avoir extrait une intention, elle est encapsulée dans un INInteraction. On INInteraction lui donne un Identifier qui correspond à l’ID unique de la commande (il sera utile ultérieurement lors de la suppression des dons d’intention qui ne sont plus valides). Ensuite, l’interaction est donnée à Siri.

L’appel au order.Intent getter extrait un OrderSoupIntent qui représente l’ordre en définissant son Quantity, Soup, Optionset son image et une expression d’appel à utiliser comme suggestion lorsque l’utilisateur enregistre une expression pour Que Siri s’associe à l’intention :

public OrderSoupIntent Intent
{
    get
    {
        var orderSoupIntent = new OrderSoupIntent();
        orderSoupIntent.Quantity = new NSNumber(Quantity);
        orderSoupIntent.Soup = new INObject(MenuItem.ItemNameKey, MenuItem.LocalizedString);

        var image = UIImage.FromBundle(MenuItem.IconImageName);
        if (!(image is null))
        {
            var data = image.AsPNG();
            orderSoupIntent.SetImage(INImage.FromData(data), "soup");
        }

        orderSoupIntent.Options = MenuItemOptions
            .ToArray<MenuItemOption>()
            .Select<MenuItemOption, INObject>(arg => new INObject(arg.Value, arg.LocalizedString))
            .ToArray<INObject>();

        var comment = "Suggested phrase for ordering a specific soup";
        var phrase = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_SOUP_SUGGESTED_PHRASE", comment);
        orderSoupIntent.SuggestedInvocationPhrase = String.Format(phrase, MenuItem.LocalizedString);

        return orderSoupIntent;
    }
}

Suppression de dons non valides

Il est important de supprimer les dons qui ne sont plus valides afin que Siri ne fasse pas de suggestions de raccourci inutiles ou confus.

Dans Soup Chef, l’écran Configurer le menu peut être utilisé pour marquer un élément de menu comme indisponible. Siri ne doit plus suggérer de raccourci pour commander l’élément de menu non disponible. Par conséquent, la RemoveDonation méthode de SoupMenuManager suppression des dons pour les éléments de menu qui ne sont plus disponibles. L’application implémente cette fonctionnalité en procédant comme suit :

  • Recherche de commandes associées à l’élément de menu désormais indisponible.
  • Saisir leurs identificateurs.
  • Suppression d’interactions qui ont les mêmes identificateurs.
void RemoveDonation(MenuItem menuItem)
{
    if (!menuItem.IsAvailable)
    {
        Order[] orderHistory = OrderManager?.OrderHistory.ToArray<Order>();
        if (orderHistory is null)
        {
            return;
        }

        string[] orderIdentifiersToRemove = orderHistory
            .Where<Order>((order) => order.MenuItem.ItemNameKey == menuItem.ItemNameKey)
            .Select<Order, string>((order) => order.Identifier.ToString())
            .ToArray<string>();

        INInteraction.DeleteInteractions(orderIdentifiersToRemove, (error) =>
        {
            if (!(error is null))
            {
                Console.WriteLine($"Failed to delete interactions with error {error.ToString()}");
            }
            else
            {
                Console.WriteLine("Successfully deleted interactions");
            }
        });
    }
}

Validation des dons réussis

La solution inclut plusieurs projets et une configuration spécifique. Dans certains cas, l’application peut se bloquer en raison d’une configuration incomplète, dans d’autres cas, il peut échouer silencieusement à donner une interaction. Il est important de valider les dons réussis et les paramètres des développeurs iOS l’aident. Accédez à Paramètres > Développeur et activez les options de développement suivantes pour afficher les dons et raccourcis récents :

  • Afficher les raccourcis récents
  • Afficher les dons sur l’écran de verrouillage

Une fois activé, chaque don réussi s’affiche sur l’écran de verrouillage et sous les options de suggestions Siri. Si après avoir exécuté votre application, vous ne voyez pas les dons là-bas, passez en revue les cas de résolution des problèmes suivants :

  1. Une application ne parvient pas à créer l’erreur OrderSoupIntent suivante :

    Impossible de créer une instance native du type « NativeLibrary.OrderSoupIntent » : la classe native n’a pas été chargée.

    Cette erreur signifie que Xamarin ne peut pas charger la classe native via la liaison Xamarin. Pour résoudre ce problème, vérifiez que la bibliothèque native inclut le code requis, référencé par le projet de liaison et que les indicateurs appropriés sont définis, comme décrit ici, définissez l’indicateur Force LoadOnsur .

  2. Une application ne parvient pas à initialiser l’instance native chargée de la classe d’intention avec l’erreur suivante :

    Impossible d’initialiser une instance du type « NativeLibrary.OrderSoupIntent » : la méthode « init » native a retourné nil.

    Le problème est lié au fichier de définition d’intention manquant. L’application Xamarin doit inclure le fichier de définition d’intention d’origine avec le Content type, comme décrit ici.

  3. Une application crée l’intention et appelle la méthode de don sans incident, mais la sortie de la console affiche un avertissement sur le type d’intention inconnu et aucun don n’est effectué :

    Impossible de donner une interaction avec OrderSoupIntent qui n’a aucun type de raccourci valide

    Pour résoudre le problème, l’intention doit être correctement définie dans la liste plist, le droit Siri doit être activé et sélectionné pour la configuration de build actuelle via les paramètres du projet.

    Info.plist de l’application :

    <key>NSUserActivityTypes</key>
    <array>
        <string>ScheduleMeetingIntent</string>
    </array>
    

    Droits.plist de l’application avec la fonctionnalité Siri :

    <key>com.apple.developer.siri</key>
    <true/>
    

    Les droits personnalisés doivent être sélectionnés pour la configuration de build ciblée. Accédez aux paramètres > de projet Générer la > signature de bundle iOS et définissez les droits personnalisés sur le fichier Entitlements.plist contenant les droits requis.

Création d’une extension Intents

Le code qui s’exécute lorsque Siri appelle une intention est placé dans une extension Intents, qui peut être ajouté en tant que nouveau projet à la même solution qu’une application Xamarin.iOS existante comme Soup Chef. Dans la solution SoupChef , l’extension est appelée SoupChefIntents.

SoupChefIntents – Info.plist et Entitlements.plist

SoupChefIntents – Info.plist

Le fichier Info.plist dans le projet SoupChefIntents définit l’identificateur de bundle comme com.xamarin.SoupChef.SoupChefIntents.

Le fichier Info.plist contient également l’entrée suivante :

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>IntentsRestrictedWhileLocked</key>
        <array/>
        <key>IntentsSupported</key>
        <array>
            <string>OrderSoupIntent</string>
        </array>
        <key>IntentsRestrictedWhileProtectedDataUnavailable</key>
        <array/>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.intents-service</string>
    <key>NSExtensionPrincipalClass</key>
    <string>IntentHandler</string>
</dict>

Dans le fichier Info.plist ci-dessus :

  • IntentsRestrictedWhileLocked répertorie les intentions à gérer lorsque l’appareil est déverrouillé.
  • IntentsSupported répertorie les intentions gérées par cette extension.
  • NSExtensionPointIdentifier spécifie le type d’extension d’application. Pour plus d’informations, consultez la documentation d’Apple.
  • NSExtensionPrincipalClass spécifie la classe qui doit être utilisée pour gérer les intentions prises en charge par cette extension.
SoupChefIntents – Droits.plist

Le fichier Entitlements.plist dans le projet SoupChefIntents dispose de la fonctionnalité Groupes d’applications. Cette fonctionnalité est configurée pour utiliser le même groupe d’applications que le projet SoupChef :

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.xamarin.SoupChef</string>
</array>

Soup Chef conserve les données avec NSUserDefaults. Pour partager des données entre l’application et l’extension d’application, ils référencent le même groupe d’applications dans leurs fichiers Entitlements.plist .

Remarque

La configuration de build du projet SoupChefIntents définit les droits personnalisés sur Entitlements.plist.

Gestion d’une tâche en arrière-plan OrderSoupIntent

Une extension Intents exécute les tâches en arrière-plan nécessaires pour un raccourci basé sur une intention personnalisée.

Siri appelle la GetHandler méthode de la IntentHandler classe (définie dans Info.plist en tant que NSExtensionPrincipalClass) pour obtenir une instance d’une classe qui s’étend OrderSoupIntentHandling, qui peut être utilisée pour gérer un OrderSoupIntent:

[Register("IntentHandler")]
public class IntentHandler : INExtension
{
    public override NSObject GetHandler(INIntent intent)
    {
        if (intent is OrderSoupIntent)
        {
            return new OrderSoupIntentHandler();
        }
        throw new Exception("Unhandled intent type: ${intent}");
    }

    protected IntentHandler(IntPtr handle) : base(handle) { }
}

OrderSoupIntentHandler, défini dans le projet SoupKit du code partagé, implémente deux méthodes importantes :

  • ConfirmOrderSoup : confirme si la tâche associée à l’intention doit être exécutée ou non
  • HandleOrderSoup : place l’ordre de soupe et répond à l’utilisateur en appelant le gestionnaire de saisie semi-automatique passée

Gestion d’une commande OrderSoupIntent qui ouvre l’application

Une application doit gérer correctement les intentions qui ne s’exécutent pas en arrière-plan. Ces intentions sont gérées de la même façon que NSUserActivity les raccourcis, dans la ContinueUserActivity méthode de AppDelegate:

public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
    var intent = userActivity.GetInteraction()?.Intent as OrderSoupIntent;
    if (!(intent is null))
    {
        HandleIntent(intent);
        return true;
    }
    // ...
}  

Fourniture d’une interface utilisateur pour une intention personnalisée

Une extension d’interface utilisateur Intents fournit une interface utilisateur personnalisée pour une extension Intents. Dans la solution SoupChef , SoupChefIntentsUI est une extension d’interface utilisateur Intents qui fournit une interface pour SoupChefIntents.

SoupChefIntentsUI – Info.plist et Entitlements.plist

SoupChefIntentsUI – Info.plist

Info.plist dans le projet SoupChefIntentsUI définit l’identificateur de bundle comme com.xamarin.SoupChef.SoupChefIntentsui.

Le fichier Info.plist contient également l’entrée suivante :

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>IntentsSupported</key>
        <array>
            <string>OrderSoupIntent</string>
        </array>
        <!-- ... -->
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.intents-ui-service</string>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
</dict>

Dans le fichier Info.plist ci-dessus :

  • IntentsSupported indique que la valeur OrderSoupIntent est gérée par cette extension d’interface utilisateur Intents.
  • NSExtensionPointIdentifier spécifie le type d’extension d’application. Pour plus d’informations, consultez la documentation d’Apple.
  • NSExtensionMainStoryboard spécifie le storyboard qui définit l’interface principale de cette extension

SoupChefIntentsUI – Droits.plist

Le projet SoupChefIntentsUI n’a pas besoin d’un fichier Entitlements.plist .

Création de l’interface utilisateur

Étant donné que info.plist pour SoupChefIntentsUI définit la NSExtensionMainStoryboard clé MainInterfacesur , le fichier MainInterace.storyboard définit l’interface de l’extension d’interface utilisateur Intents.

Dans ce storyboard, il existe un seul contrôleur d’affichage, de type IntentViewController. Il fait référence à deux vues :

  • invoiceView, de type InvoiceView
  • confirmationView, de type ConfirmOrderView

Remarque

Les interfaces pour invoiceView et confirmationView sont définies dans Main.storyboard en tant que vues secondaires. Visual Studio pour Mac et Visual Studio 2017 ne prennent pas en charge l’affichage ou la modification des vues secondaires ; pour ce faire, ouvrez Main.storyboard dans le Générateur d’interface de Xcode.

IntentViewController implémente le IINUIHostedViewControlling interface utilisée pour fournir une interface personnalisée lors de l’utilisation des intentions Siri. LeConfigureViewla méthode est appelée pour personnaliser l’interface, affichant la confirmation ou la facture, selon que l’interaction est confirmée () ou a été exécutée avec succès (INIntentHandlingStatus.ReadyINIntentHandlingStatus.Success) :

[Export("configureViewForParameters:ofInteraction:interactiveBehavior:context:completion:")]
public void ConfigureView(
    NSSet<INParameter> parameters,
    INInteraction interaction,
    INUIInteractiveBehavior interactiveBehavior,
    INUIHostedViewContext context,
    INUIHostedViewControllingConfigureViewHandler completion)
{
    // ...
    if (interaction.IntentHandlingStatus == INIntentHandlingStatus.Ready)
    {
        desiredSize = DisplayInvoice(order, intent);
    }
    else if(interaction.IntentHandlingStatus == INIntentHandlingStatus.Success)
    {
        var response = interaction.IntentResponse as OrderSoupIntentResponse;
        if (!(response is null))
        {
            desiredSize = DisplayOrderConfirmation(order, intent, response);
        }
    }
    completion(true, parameters, desiredSize);
}

Conseil

Pour plus d’informations sur la ConfigureView méthode, regardez la présentation WWDC 2017 d’Apple, What’s New in SiriKit.

Création d’un raccourci vocal

Soup Chef fournit une interface permettant d’attribuer un raccourci vocal à chaque commande, ce qui permet de commander la soupe avec Siri. En fait, l’interface utilisée pour enregistrer et affecter des raccourcis vocaux est fournie par iOS et nécessite peu de code personnalisé.

Dans OrderDetailViewController, lorsqu’un utilisateur appuie sur la ligne Ajouter à Siri de la table, la RowSelected méthode présente un écran pour ajouter ou modifier un raccourci vocal :

public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
    // ...
    else if (TableConfiguration.Sections[indexPath.Section].Type == OrderDetailTableConfiguration.SectionType.VoiceShortcut)
    {
        INVoiceShortcut existingShortcut = VoiceShortcutDataManager?.VoiceShortcutForOrder(Order);
        if (!(existingShortcut is null))
        {
            var editVoiceShortcutViewController = new INUIEditVoiceShortcutViewController(existingShortcut);
            editVoiceShortcutViewController.Delegate = this;
            PresentViewController(editVoiceShortcutViewController, true, null);
        }
        else
        {
            // Since the app isn't yet managing a voice shortcut for
            // this order, present the add view controller
            INShortcut newShortcut = new INShortcut(Order.Intent);
            if (!(newShortcut is null))
            {
                var addVoiceShortcutVC = new INUIAddVoiceShortcutViewController(newShortcut);
                addVoiceShortcutVC.Delegate = this;
                PresentViewController(addVoiceShortcutVC, true, null);
            }
        }
    }
}

Selon qu’il existe ou non un raccourci vocal existant pour l’ordre actuellement affiché, RowSelected présente un contrôleur de vue de type INUIEditVoiceShortcutViewController ou INUIAddVoiceShortcutViewController. Dans chaque cas, OrderDetailViewController se définit comme le contrôleur de Delegatevue , c’est pourquoi il implémente également Voir IINUIAddVoiceShortcutViewControllerDelegate et IINUIEditVoiceShortcutViewControllerDelegate.

Test sur l’appareil

Pour exécuter Soup Chef sur un appareil, suivez les instructions de cette section. Lisez également la note sur l’approvisionnement automatique.

Groupe d’applications, ID d’application, profils d’approvisionnement

Dans la section Certificats, ID et profils du portail des développeurs Apple, procédez comme suit :

  • Créez un groupe d’applications pour partager des données entre l’application Soup Chef et ses extensions. Par exemple : group.com.yourcompanyname.SoupChef

  • Créez trois ID d’application : un pour l’application lui-même, un pour l’extension Intentions et un pour l’extension d’interface utilisateur Intents. Par exemple :

    • Application : com.yourcompanyname.SoupChef

      • Pour cet ID d’application, affectez les fonctionnalités SiriKit et Groupes d’applications.
    • Extension Intentions : com.yourcompanyname.SoupChef.Intents

      • À cet ID d’application, affectez la fonctionnalité Groupes d’applications.
    • Extension de l’interface utilisateur intents : com.yourcompanyname.SoupChef.Intentsui

      • Cet ID d’application n’a pas besoin de fonctionnalités spéciales.
  • Après avoir créé les ID d’application ci-dessus, modifiez la fonctionnalité Groupes d’applications affectée à l’application et à l’extension Intentions, en spécifiant le groupe d’applications spécifique créé précédemment.

  • Créez trois nouveaux profils d’approvisionnement de développement, un pour chacun des nouveaux ID d’application.

  • Téléchargez ces profils d’approvisionnement et double-cliquez sur chacun d’eux pour l’installer. Si Visual Studio pour Mac ou Visual Studio 2017 est déjà en cours d’exécution, redémarrez-le pour vous assurer qu’il inscrit les nouveaux profils d’approvisionnement.

Modification d’Info.plist, de Entitlements.plist et du code source

Dans Visual Studio pour Mac ou Visual Studio 2017, procédez comme suit :

  • Mettez à jour les différents fichiers Info.plist dans la solution. Définissez l’application, l’extension Intents et l’identificateur de bundle d’extension intentions de l’interface utilisateur sur les ID d’application définis précédemment :

    • Application : com.yourcompanyname.SoupChef
    • Extension intentions : com.yourcompanyname.SoupChef.Intents
    • Extension de l’interface utilisateur intents : com.yourcompanyname.SoupChef.Intentsui
  • Mettez à jour le fichier Entitlements.plist pour le projet SoupChef :

    • Pour la fonctionnalité Groupes d’applications, définissez le groupe sur le nouveau groupe d’applications créé précédemment (dans l’exemple ci-dessus, il s’agissait de group.com.yourcompanyname.SoupChef).
    • Vérifiez que SiriKit est activé.
  • Mettez à jour le fichier Entitlements.plist pour le projet SoupChefIntents :

    • Pour la fonctionnalité Groupes d’applications, définissez le groupe sur le nouveau groupe d’applications créé précédemment (dans l’exemple ci-dessus, il s’agissait de group.com.yourcompanyname.SoupChef).
  • Enfin, ouvrez NSUserDefaultsHelper.cs. Définissez la AppGroup variable sur la valeur de votre nouveau groupe d’applications (par exemple, définissez-la sur group.com.yourcompanyname.SoupChef).

Configuration des paramètres de build

Dans Visual Studio pour Mac ou Visual Studio 2017 :

  • Ouvrez les options/propriétés du projet SoupChef . Sous l’onglet Signature de bundle iOS, définissez l’identité de signature sur le profil d’approvisionnement automatique et d’approvisionnement sur le nouveau profil d’approvisionnement spécifique à l’application que vous avez créé précédemment.

  • Ouvrez les options/propriétés du projet SoupChefIntents . Sous l’onglet Signature de bundle iOS, définissez l’identité de signature sur le profil d’approvisionnement automatique et d’approvisionnement sur le nouveau profil d’approvisionnement spécifique à l’extension Intents que vous avez créé précédemment.

  • Ouvrez les options/propriétés du projet SoupChefIntentsUI . Sous l’onglet Signature de bundle iOS, définissez l’identité de signature sur le profil d’approvisionnement automatique et d’approvisionnement sur le nouveau profil d’approvisionnement spécifique à l’interface utilisateur intents que vous avez créé précédemment.

Avec ces modifications en place, l’application s’exécute sur un appareil iOS.

Provisionnement automatique

Vous pouvez utiliser l’approvisionnement automatique pour accomplir une grande partie de ces tâches d’approvisionnement directement dans l’IDE. Toutefois, l’approvisionnement automatique ne configure pas les groupes d’applications. Vous devez configurer manuellement les fichiers Entitlements.plist avec le nom du groupe d’applications que vous souhaitez utiliser, visiter le portail des développeurs Apple pour créer le groupe d’applications, affecter ce groupe d’applications à chaque ID d’application créé par l’approvisionnement automatique, régénérer les profils d’approvisionnement (application, extension Intentions, extension Intentions, extension Intents UI) pour inclure le groupe d’applications nouvellement créé, et téléchargez-les et installez-les.