Condividi tramite


Implementazione di SiriKit in Xamarin.iOS

Questo articolo illustra i passaggi necessari per implementare il supporto di SiriKit in app Xamarin.iOS.

Una novità di iOS 10, SiriKit consente a un'app Xamarin.iOS di fornire servizi accessibili all'utente usando Siri e l'app Mappe in un dispositivo iOS. Questo articolo illustra i passaggi necessari per implementare il supporto di SiriKit nelle app Xamarin.iOS aggiungendo le estensioni delle finalità necessarie, le estensioni dell'interfaccia utente intents e il vocabolario.

Siri funziona con il concetto di domini, gruppi di azioni di conoscenza per le attività correlate. Ogni interazione che l'app ha con Siri deve rientrare in uno dei domini del servizio noti come indicato di seguito:

  • Audio o videochiamate.
  • Prenotare un giro.
  • Gestione degli allenamenti.
  • Messaggistica.
  • Ricerca di foto.
  • Invio o ricezione di pagamenti.

Quando l'utente effettua una richiesta di Siri che coinvolge uno dei servizi dell'estensione dell'app, SiriKit invia l'estensione un oggetto Intent che descrive la richiesta dell'utente insieme ai dati di supporto. L'estensione dell'app genera quindi l'oggetto Response appropriato per la finalità specificata, descrivendo in dettaglio come l'estensione può gestire la richiesta.

Questa guida presenta un rapido esempio di inclusione del supporto di SiriKit in un'app esistente. Ai fini di questo esempio, useremo l'app MonkeyChat fittizia:

Icona MonkeyChat

MonkeyChat mantiene il proprio libro contatti degli amici dell'utente, ognuno associato a un nome di schermata (ad esempio Bobo) e consente all'utente di inviare chat di testo a ogni amico in base al nome dello schermo.

Estensione dell'app con SiriKit

Come illustrato nella guida Informazioni sui concetti di SiriKit, esistono tre parti principali coinvolte nell'estensione di un'app con SiriKit:

Estensione dell'app con il diagramma SiriKit

tra cui:

  1. Estensione finalità: verifica le risposte degli utenti, conferma che l'app può gestire la richiesta ed esegue effettivamente l'attività per soddisfare la richiesta dell'utente.
  2. Estensione - interfaccia utente finalità Facoltativa, fornisce un'interfaccia utente personalizzata alle risposte nell'ambiente Siri e può portare l'interfaccia utente e la personalizzazione delle app in Siri per arricchire l'esperienza dell'utente.
  3. App : fornisce all'app vocabolari specifici dell'utente per facilitare l'uso di Siri.

Tutti questi elementi e i passaggi da includere nell'app verranno trattati in dettaglio nelle sezioni seguenti.

Preparazione dell'app

SiriKit è basato sulle estensioni, tuttavia, prima di aggiungere qualsiasi estensione all'app, ci sono alcune cose che lo sviluppatore deve fare per aiutare con l'adozione di SiriKit.

Spostamento di codice condiviso comune

In primo luogo, lo sviluppatore può spostare parte del codice comune che verrà condiviso tra l'app e le estensioni in progetti condivisi, librerie di classi portabili (PCLS) o librerie native.

Le estensioni dovranno essere in grado di eseguire tutte le operazioni eseguite dall'app. In termini di app MonkeyChat di esempio, elementi come la ricerca di contatti, l'aggiunta di nuovi contatti, l'invio di messaggi e il recupero della cronologia dei messaggi.

Spostando questo codice comune in un progetto condiviso, una libreria di classi portabile o una libreria nativa, semplifica la manutenzione del codice in un'unica posizione comune e garantisce che l'estensione e l'app padre forniscano esperienze e funzionalità uniformi per l'utente.

Nel caso dell'app di esempio MonkeyChat, i modelli di dati e il codice di elaborazione, ad esempio l'accesso alla rete e al database, verranno spostati in una libreria nativa.

Effettuare le operazioni seguenti:

  1. Avviare Visual Studio per Mac e aprire l'app MonkeyChat.

  2. Fare clic con il pulsante destro del mouse sul nome della soluzione nel riquadro della soluzione e scegliere Aggiungi>nuovo progetto...:

    Aggiungere un nuovo progetto

  3. Selezionare Libreria di classi libreria> iOS>e fare clic sul pulsante Avanti:

    Selezionare Libreria di classi

  4. Immettere MonkeyChatCommon per Nome e fare clic sul pulsante Crea :

    Immettere MonkeyChatCommon come Nome

  5. Fare clic con il pulsante destro del mouse sulla cartella Riferimenti dell'app principale nel Esplora soluzioni e scegliere Modifica riferimenti.... Controllare il progetto MonkeyChatCommon e fare clic sul pulsante OK:

    Controllare il progetto MonkeyChatCommon

  6. Nella Esplora soluzioni trascinare il codice condiviso comune dall'app principale alla libreria nativa.

  7. Nel caso di MonkeyChat, trascinare le cartelle DataModels e Processors dall'app principale in Native Library:

    Cartelle DataModels e Processors nella Esplora soluzioni

Modificare uno qualsiasi dei file spostati in Native Library e modificare lo spazio dei nomi in modo che corrisponda a quello della libreria. Ad esempio, passando MonkeyChat a MonkeyChatCommon:

using System;
namespace MonkeyChatCommon
{
    /// <summary>
    /// A message sent from one user to another within a conversation.
    /// </summary>
    public class MonkeyMessage
    {
        public MonkeyMessage ()
        {
        }
        ...
    }
}

Tornare quindi all'app principale e aggiungere un'istruzione using per lo spazio dei nomi di Native Library ovunque l'app usi una delle classi spostate:

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;
using MonkeyChatCommon;

namespace MonkeyChat
{
    public partial class MasterViewController : UITableViewController
    {
        public DetailViewController DetailViewController { get; set; }

        DataSource dataSource;
        ...
    }
}

Progettazione dell'app per le estensioni

In genere, un'app eseguirà l'iscrizione a più finalità e lo sviluppatore deve assicurarsi che l'app sia progettata per il numero appropriato di estensioni finalità.

Nella situazione in cui un'app richiede più finalità, lo sviluppatore ha la possibilità di posizionare tutte le finalità in un'estensione di finalità o di creare un'estensione di finalità separata per ogni finalità.

Se si sceglie di creare un'estensione di finalità separata per ogni finalità, lo sviluppatore potrebbe duplicare una grande quantità di codice boilerplate in ogni estensione e creare una grande quantità di sovraccarico di processore e memoria.

Per scegliere tra le due opzioni, verificare se una delle finalità appartiene naturalmente. Ad esempio, un'app che effettua chiamate audio e video potrebbe voler includere entrambe le finalità in un'unica estensione di finalità perché gestisce attività simili e potrebbe fornire il maggior riutilizzo del codice.

Per qualsiasi intento o gruppo di finalità che non rientrano in un gruppo esistente, creare una nuova estensione per finalità nella soluzione dell'app per includerle.

Impostazione dei diritti obbligatori

Qualsiasi app Xamarin.iOS che include l'integrazione di SiriKit deve avere i diritti corretti impostati. Se lo sviluppatore non imposta correttamente questi diritti obbligatori, non sarà in grado di installare o testare l'app in hardware iOS 10 (o versione successiva) reale, che è necessario anche perché il simulatore iOS 10 non supporta SiriKit.

Effettuare le operazioni seguenti:

  1. Fare doppio clic sul Entitlements.plist file nel Esplora soluzioni per aprirlo per la modifica.

  2. Passare alla scheda Origine.

  3. Aggiungere la com.apple.developer.siri proprietà , impostare Type su Boolean e Value su Yes:

    Aggiungere la proprietà com.apple.developer.siri

  4. Salvare le modifiche apportate al file.

  5. Fare doppio clic sul file di progetto nel Esplora soluzioni per aprirlo per la modifica.

  6. Selezionare Firma bundle iOS e assicurarsi che il Entitlements.plist file sia selezionato nel campo Diritti personalizzati:

    Selezionare il file Entitlements.plist nel campo Diritti personalizzati

  7. Fare clic su OK per salvare le modifiche.

Al termine, il file dell'app Entitlements.plist dovrebbe essere simile al seguente (in aperto in un editor esterno):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.siri</key>
    <true/>
</dict>
</plist>

Provisioning corretto dell'app

A causa della rigorosa sicurezza che Apple ha inserito intorno al framework SiriKit, qualsiasi app Xamarin.iOS che implementa SiriKit deve avere l'ID app e gli entitlement corretti (vedere la sezione precedente) e deve essere firmata con un profilo di provisioning appropriato.

Eseguire le operazioni seguenti sul Mac:

  1. In un Web browser passare a e accedere all'account https://developer.apple.com .

  2. Fare clic su Certificati, identificatori e profili.

  3. Selezionare Profili di provisioning e selezionare ID app, quindi fare clic sul + pulsante .

  4. Immettere un nome per il nuovo profilo.

  5. Immettere un ID bundle seguendo la raccomandazione di denominazione di Apple.

  6. Scorrere verso il basso fino alla sezione servizio app s, selezionare SiriKit e fare clic sul pulsante Continua:

    Selezionare SiriKit

  7. Verificare tutte le impostazioni, quindi Inviare l'ID app.

  8. Selezionare Provisioning Profiles Development (Sviluppo profili>di provisioning), fare clic sul + pulsante , selezionare l'ID Apple e quindi fare clic su Continua.

  9. Fare clic su Seleziona tutto, quindi su Continua.

  10. Fare di nuovo clic su Seleziona tutto , quindi su Continua.

  11. Immettere un nome profilo usando i suggerimenti di denominazione di Apple, quindi fare clic su Continua.

  12. Avviare Xcode.

  13. Dal menu Xcode selezionare Preferenze...

  14. Selezionare Account, quindi fare clic sul pulsante Visualizza dettagli...

    Selezionare Account

  15. Fare clic sul pulsante Scarica tutti i profili nell'angolo inferiore sinistro:

    Scarica tutti i profili

  16. Verificare che il profilo di provisioning creato in precedenza sia stato installato in Xcode.

  17. Aprire il progetto per aggiungere il supporto di SiriKit a in Visual Studio per Mac.

  18. Fare doppio clic sul Info.plist file nel Esplora soluzioni.

  19. Assicurarsi che l'identificatore del bundle corrisponda a quello creato nel portale per sviluppatori di Apple precedente:

    Identificatore del bundle

  20. Nella Esplora soluzioni selezionare il progetto.

  21. Fare clic con il pulsante destro del mouse sul progetto e scegliere Opzioni.

  22. Selezionare Firma bundle iOS, selezionare l'identità di firma e il profilo di provisioning creati in precedenza:

    Selezionare l'identità di firma e il profilo di provisioning

  23. Fare clic su OK per salvare le modifiche.

Importante

Il test di SiriKit funziona solo su un dispositivo hardware iOS 10 reale e non nel simulatore iOS 10. Se si verificano problemi durante l'installazione di un'app Xamarin.iOS abilitata per SiriKit in hardware reale, assicurarsi che i diritti necessari, l'ID app, l'identificatore di firma e il profilo di provisioning siano stati configurati correttamente nel portale per sviluppatori di Apple e Visual Studio per Mac.

Richiesta di autorizzazione siri

Prima che l'app aggiunga qualsiasi vocabolario specifico dell'utente o le estensioni finalità si connetta a Siri, deve richiedere l'autorizzazione dell'utente per accedere a Siri.

Modificare il file dell'app Info.plist , passare alla visualizzazione Origine e aggiungere la NSSiriUsageDescription chiave con un valore stringa che descrive come l'app userà Siri e quali tipi di dati verranno inviati. Ad esempio, l'app MonkeyChat potrebbe dire "I contatti MonkeyChat verranno inviati a Siri":

NSSiriUsageDescription nell'editor Info.plist

Chiamare il RequestSiriAuthorization metodo della INPreferences classe all'avvio dell'app. Modificare la AppDelegate.cs classe e fare in modo che il FinishedLaunching metodo sia simile al seguente:

using Intents;
...

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{

    // Request access to Siri
    INPreferences.RequestSiriAuthorization ((INSiriAuthorizationStatus status) => {
        // Respond to returned status
        switch (status) {
        case INSiriAuthorizationStatus.Authorized:
            break;
        case INSiriAuthorizationStatus.Denied:
            break;
        case INSiriAuthorizationStatus.NotDetermined:
            break;
        case INSiriAuthorizationStatus.Restricted:
            break;
        }
    });

    return true;
}

La prima volta che viene chiamato questo metodo, viene visualizzato un avviso che richiede all'utente di consentire all'app di accedere a Siri. Il messaggio che lo sviluppatore aggiunto alla NSSiriUsageDescription precedente verrà visualizzato in questo avviso. Se l'utente nega inizialmente l'accesso, può usare l'app Impostazioni per concedere l'accesso all'app.

In qualsiasi momento, l'app può controllare la capacità dell'app di accedere a Siri chiamando il SiriAuthorizationStatus metodo della INPreferences classe .

Localizzazione e Siri

In un dispositivo iOS l'utente è in grado di selezionare una lingua per Siri diversa, quindi l'impostazione predefinita del sistema. Quando si usano dati localizzati, l'app dovrà usare il SiriLanguageCode metodo della INPreferences classe per ottenere il codice della lingua da Siri. Ad esempio:

var language = INPreferences.SiriLanguageCode();

// Take action based on language
if (language == "en-US") {
    // Do something...
}

Aggiunta di un vocabolario specifico dell'utente

Il vocabolario specifico dell'utente fornirà parole o frasi univoche per i singoli utenti dell'app. Questi verranno forniti in fase di esecuzione dall'app principale (non dalle estensioni dell'app) come set ordinato di termini, ordinati in una priorità di utilizzo più significativa per gli utenti, con i termini più importanti all'inizio dell'elenco.

Il vocabolario specifico dell'utente deve appartenere a una delle categorie seguenti:

  • Nomi dei contatti (non gestiti dal framework Contatti).
  • Tag foto.
  • Nomi album fotografici.
  • Nomi di allenamento.

Quando si seleziona la terminologia da registrare come vocabolario personalizzato, scegliere solo i termini che potrebbero essere fraintesi da un utente che non ha familiarità con l'app. Non registrare mai termini comuni come "My Workout" o "My Album". Ad esempio, l'app MonkeyChat registrerà i nomi alternativi associati a ogni contatto nella rubrica dell'utente.

L'app fornisce il vocabolario specifico dell'utente chiamando il SetVocabularyStrings metodo della INVocabulary classe e passando una NSOrderedSet raccolta dall'app principale. L'app deve sempre chiamare il RemoveAllVocabularyStrings metodo per prima cosa, per rimuovere eventuali termini esistenti prima di aggiungerne di nuovi. Ad esempio:

using System;
using System.Linq;
using System.Collections.Generic;
using Foundation;
using Intents;

namespace MonkeyChatCommon
{
    public class MonkeyAddressBook : NSObject
    {
        #region Computed Properties
        public List<MonkeyContact> Contacts { get; set; } = new List<MonkeyContact> ();
        #endregion

        #region Constructors
        public MonkeyAddressBook ()
        {
        }
        #endregion

        #region Public Methods
        public NSOrderedSet<NSString> ContactNicknames ()
        {
            var nicknames = new NSMutableOrderedSet<NSString> ();

            // Sort contacts by the last time used
            var query = Contacts.OrderBy (contact => contact.LastCalledOn);

            // Assemble ordered list of nicknames by most used to least
            foreach (MonkeyContact contact in query) {
                nicknames.Add (new NSString (contact.ScreenName));
            }

            // Return names
            return new NSOrderedSet<NSString> (nicknames.AsSet ());
        }

        // This method MUST only be called on a background thread!
        public void UpdateUserSpecificVocabulary ()
        {
            // Clear any existing vocabulary
            INVocabulary.SharedVocabulary.RemoveAllVocabularyStrings ();

            // Register new vocabulary
            INVocabulary.SharedVocabulary.SetVocabularyStrings (ContactNicknames (), INVocabularyStringType.ContactName);
        }
        #endregion
    }
}

Con questo codice sul posto, potrebbe essere chiamato come segue:

using System;
using System.Threading;
using UIKit;
using MonkeyChatCommon;
using Intents;

namespace MonkeyChat
{
    public partial class ViewController : UIViewController
    {
        #region AppDelegate Access
        public AppDelegate ThisApp {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Constructors
        protected ViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do we have access to Siri?
            if (INPreferences.SiriAuthorizationStatus == INSiriAuthorizationStatus.Authorized) {
                // Yes, update Siri's vocabulary
                new Thread (() => {
                    Thread.CurrentThread.IsBackground = true;
                    ThisApp.AddressBook.UpdateUserSpecificVocabulary ();
                }).Start ();
            }
        }

        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
            // Release any cached data, images, etc that aren't in use.
        }
        #endregion
    }
}

Importante

Siri considera il vocabolario personalizzato come suggerimenti e incorpora la maggior parte della terminologia possibile. Tuttavia, lo spazio per il vocabolario personalizzato è limitato rendendo importante registrare solo la terminologia che potrebbe generare confusione, mantenendo quindi minimo il numero totale di termini registrati.

Per altre informazioni, vedere le informazioni di riferimento sul vocabolario specifiche dell'utente e le informazioni di riferimento sul vocabolario personalizzato di Apple.

Aggiunta di un vocabolario specifico dell'app

Il vocabolario specifico dell'app definisce le parole e le frasi specifiche che saranno note a tutti gli utenti dell'app, ad esempio i tipi di veicolo o i nomi degli allenamenti. Poiché fanno parte dell'applicazione, vengono definiti in un AppIntentVocabulary.plist file come parte del bundle principale dell'app. Inoltre, queste parole e frasi devono essere localizzate.

I termini del vocabolario specifico dell'app devono appartenere a una delle categorie seguenti:

  • Opzioni ride.
  • Nomi di allenamento.

Il file vocabolario specifico dell'app contiene due chiavi di livello radice:

  • ParameterVocabulariesObbligatorio: definisce i termini personalizzati dell'app e i parametri delle finalità a cui si applicano.
  • IntentPhrasesFacoltativo: contiene frasi di esempio che usano i termini personalizzati definiti in ParameterVocabularies.

Ogni voce in ParameterVocabularies deve specificare una stringa ID, un termine e la finalità a cui si applica il termine. Inoltre, un singolo termine può essere applicato a più finalità.

Per un elenco completo dei valori accettabili e della struttura di file necessaria, vedere Informazioni di riferimento sul formato del file del vocabolario dell'app di Apple.

Per aggiungere un AppIntentVocabulary.plist file al progetto dell'app, eseguire le operazioni seguenti:

  1. Fare clic con il pulsante destro del mouse sul nome del progetto nella Esplora soluzioni e scegliere Aggiungi>nuovo file...>iOS:

    Aggiungere un elenco di proprietà

  2. Fare doppio clic sul AppIntentVocabulary.plist file nel Esplora soluzioni per aprirlo per la modifica.

  3. Fare clic su + per aggiungere una chiave, impostare Il nome su ParameterVocabularies e Tipo su Array:

    Impostare Name su ParameterVocabularies e type su Array

  4. Espandere ParameterVocabularies e fare clic sul + pulsante e impostare Il tipo su Dictionary:

    Impostare Il tipo su Dizionario

  5. Fare clic su + per aggiungere una nuova chiave, impostare Il nome su ParameterNames e Tipo su Array:

    Impostare Name su ParameterNames e Type su Array

  6. Fare clic su + per aggiungere una nuova chiave con il tipo di String e il valore come uno dei nomi dei parametri disponibili. Ad esempio, INStartWorkoutIntent.workoutName:

    Chiave INStartWorkoutIntent.workoutName

  7. Aggiungere la ParameterVocabulary chiave alla ParameterVocabularies chiave con il tipo di Array:

    Aggiungere la chiave ParameterVocabulary alla chiave ParameterVocabularies con il tipo di matrice

  8. Aggiungere una nuova chiave con il tipo di Dictionary:

    Aggiungere una nuova chiave con il tipo di dizionario in Visual Studio per Mac.

  9. Aggiungere la VocabularyItemIdentifier chiave con il tipo di String e specificare un ID univoco per il termine:

    Aggiungere la chiave VocabularyItemIdentifier con il tipo di stringa e specificare un ID univoco

  10. Aggiungere la VocabularyItemSynonyms chiave con il tipo di Array:

    Aggiungere la chiave VocabularyItemSynonyms con il tipo di matrice

  11. Aggiungere una nuova chiave con il tipo di Dictionary:

    Aggiungere un'altra nuova chiave con il tipo di dizionario in Visual Studio per Mac.

  12. Aggiungere la VocabularyItemPhrase chiave con il tipo di String e il termine che l'app definisce:

    Aggiungere la chiave VocabularyItemPhrase con il tipo di stringa e il termine che l'app definisce

  13. Aggiungere la VocabularyItemPronunciation chiave con il tipo di String e la pronuncia fonetica del termine:

    Aggiungere la chiave VocabularyItemPronunciation con il tipo di stringa e la pronuncia fonetica del termine

  14. Aggiungere la VocabularyItemExamples chiave con il tipo di Array:

    Aggiungere la chiave VocabularyItemExamples con il tipo di matrice

  15. Aggiungere alcune String chiavi con usi di esempio del termine :

    Aggiungere alcune chiavi Stringa con usi di esempio del termine in Visual Studio per Mac.

  16. Ripetere i passaggi precedenti per qualsiasi altro termine personalizzato che l'app deve definire.

  17. Comprimere la ParameterVocabularies chiave.

  18. Aggiungere la IntentPhrases chiave con il tipo di Array:

    Aggiungere la chiave IntentPhrases con il tipo di matrice

  19. Aggiungere una nuova chiave con il tipo di Dictionary:

    Aggiungere una nuova chiave aggiuntiva con il tipo di dizionario in Visual Studio per Mac.

  20. Aggiungere la IntentName chiave con il tipo di String e la finalità per l'esempio:

    Aggiungere la chiave IntentName con il tipo di stringa e la finalità per l'esempio

  21. Aggiungere la IntentExamples chiave con il tipo di Array:

    Aggiungere la chiave IntentExamples con il tipo di matrice

  22. Aggiungere alcune String chiavi con usi di esempio del termine :

    Aggiungere alcune chiavi stringhe aggiuntive con usi di esempio del termine in Visual Studio per Mac.

  23. Ripetere i passaggi precedenti per tutte le finalità di cui l'app deve fornire un esempio di utilizzo.

Importante

Verrà AppIntentVocabulary.plist registrato con Siri nei dispositivi di test durante lo sviluppo e potrebbe essere necessario del tempo per Siri incorporare il vocabolario personalizzato. Di conseguenza, il tester dovrà attendere alcuni minuti prima di tentare di testare il vocabolario specifico dell'app quando è stato aggiornato.

Per altre informazioni, vedi informazioni di riferimento sul vocabolario specifico dell'app e Riferimento al vocabolario personalizzato di Apple.

Aggiunta di un'estensione intents

Ora che l'app è stata preparata per adottare SiriKit, lo sviluppatore dovrà aggiungere una o più estensioni delle finalità alla soluzione per gestire le finalità necessarie per l'integrazione di Siri.

Per ogni estensione intents obbligatoria, eseguire le operazioni seguenti:

  • Aggiungere un progetto Di estensione finalità alla soluzione app Xamarin.iOS.
  • Configurare il file dell'estensione Info.plist intents.
  • Modificare la classe principale Dell'estensione finalità.

Per altre informazioni, vedere le informazioni di riferimento sulle estensioni intenti e Informazioni di riferimento sull'estensione per la creazione delle finalità di Apple.

Creazione dell'estensione

Per aggiungere un'estensione finalità alla soluzione, eseguire le operazioni seguenti:

  1. Fare clic con il pulsante destro del mouse sul nome della soluzione nel riquadro della soluzione e scegliere Aggiungi>nuovo progetto.

  2. Nella finestra di dialogo selezionare Estensioni estensioni iOS>Estensioni> finalità e fare clic sul pulsante Avanti:

    Selezionare Estensione finalità

  3. Immettere quindi un nome per l'estensione della finalità e fare clic sul pulsante Avanti :

    Immettere un nome per l'estensione della finalità.

  4. Infine, fare clic sul pulsante Crea per aggiungere l'estensione finalità alla soluzione app:

    Aggiungere l'estensione della finalità alla soluzione delle app.

  5. Nella Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Riferimenti dell'estensione finalità appena creata. Controllare il nome del progetto comune di libreria di codice condiviso (creato in precedenza dall'app) e fare clic sul pulsante OK :

    Selezionare il nome del progetto comune di libreria di codice condiviso.

Ripetere questi passaggi per il numero di estensioni delle finalità (in base alla sezione Progettazione dell'app per le estensioni precedente) che l'app richiederà.

Configurazione di Info.plist

Per ognuna delle estensioni finalità aggiunte alla soluzione dell'app, è necessario configurare nei Info.plist file per l'uso con l'app.

Proprio come qualsiasi estensione dell'app tipica, l'app avrà le chiavi esistenti di NSExtension e NSExtensionAttributes. Per un'estensione finalità sono disponibili due nuovi attributi che devono essere configurati:

Due nuovi attributi che devono essere configurati

  • IntentsSupported : è obbligatorio ed è costituito da una matrice di nomi di classe finalità che l'app vuole supportare dall'estensione della finalità.
  • IntentsRestrictedWhileLocked : chiave facoltativa per l'app per specificare il comportamento della schermata di blocco dell'estensione. È costituita da una matrice di nomi di classe finalità che l'app vuole richiedere all'utente di eseguire l'accesso per l'uso dall'estensione della finalità.

Per configurare il file dell'estensione finalità, fare doppio clic su di Info.plist esso nel Esplora soluzioni per aprirlo per la modifica. Passare quindi alla visualizzazione Origine , quindi espandere i NSExtension tasti e NSExtensionAttributes nell'editor:

Espandere la IntentsSupported chiave e aggiungere il nome di qualsiasi classe intenta supportata da questa estensione. Per l'app MonkeyChat di esempio, supporta :INSendMessageIntent

Se l'app richiede facoltativamente che l'utente sia connesso al dispositivo per usare una determinata finalità, espandere la IntentRestrictedWhileLocked chiave e aggiungere i nomi di classe delle finalità con accesso limitato. Per l'app MonkeyChat di esempio, l'utente deve essere connesso per inviare un messaggio di chat in modo che sia stato aggiunto INSendMessageIntent:

Per un elenco completo dei domini finalità disponibili, vedere Informazioni di riferimento per i domini finalità di Apple.

Configurazione della classe principale

Successivamente, lo sviluppatore dovrà configurare la classe principale che funge da punto di ingresso principale per l'estensione della finalità in Siri. Deve essere una sottoclasse di INExtension cui è conforme al IINIntentHandler delegato. Ad esempio:

using System;
using System.Collections.Generic;

using Foundation;
using Intents;

namespace MonkeyChatIntents
{
    [Register ("IntentHandler")]
    public class IntentHandler : INExtension, IINSendMessageIntentHandling, IINSearchForMessagesIntentHandling, IINSetMessageAttributeIntentHandling
    {
        #region Constructors
        protected IntentHandler (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override NSObject GetHandler (INIntent intent)
        {
            // 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 this;
        }
        #endregion
        ...
    }
}

Esiste un metodo solitario che l'app deve implementare nella classe principale Dell'estensione finalità, ovvero il GetHandler metodo . Questo metodo viene passato un intento da SiriKit e l'app deve restituire un gestore finalità corrispondente al tipo della finalità specificata.

Poiché l'app MonkeyChat di esempio gestisce una sola finalità, viene restituita nel GetHandler metodo . Se l'estensione ha gestito più finalità, lo sviluppatore aggiunge una classe per ogni tipo di finalità e restituisce un'istanza in questo caso in base all'oggetto Intent passato al metodo .

Gestione della fase di risoluzione

La fase di risoluzione è la posizione in cui l'estensione della finalità chiarirà e convaliderà i parametri passati da Siri e sono stati impostati tramite la conversazione dell'utente.

Per ogni parametro inviato da Siri, è presente un Resolve metodo . L'app dovrà implementare questo metodo per ogni parametro che l'app potrebbe richiedere assistenza di Siri per ottenere la risposta corretta dall'utente.

Nel caso dell'app MonkeyChat di esempio, l'estensione della finalità richiederà a uno o più destinatari di inviare il messaggio. Per ogni destinatario nell'elenco, l'estensione dovrà eseguire una ricerca contatto che può avere il risultato seguente:

  • Viene trovato esattamente un contatto corrispondente.
  • Vengono trovati due o più contatti corrispondenti.
  • Non vengono trovati contatti corrispondenti.

Inoltre, MonkeyChat richiede il contenuto per il corpo del messaggio. Se l'utente non ha fornito questo valore, Siri deve richiedere all'utente il contenuto.

L'estensione della finalità dovrà gestire correttamente ognuno di questi casi.

[Export ("resolveRecipientsForSearchForMessages:withCompletion:")]
public void ResolveRecipients (INSendMessageIntent intent, Action<INPersonResolutionResult []> completion)
{
    var recipients = intent.Recipients;
    // If no recipients were provided we'll need to prompt for a value.
    if (recipients.Length == 0) {
        completion (new INPersonResolutionResult [] { (INPersonResolutionResult)INPersonResolutionResult.NeedsValue });
        return;
    }

    var resolutionResults = new List<INPersonResolutionResult> ();

    foreach (var recipient in recipients) {
        var matchingContacts = new INPerson [] { recipient }; // Implement your contact matching logic here to create an array of matching contacts
        if (matchingContacts.Length > 1) {
            // We need Siri's help to ask user to pick one from the matches.
            resolutionResults.Add (INPersonResolutionResult.GetDisambiguation (matchingContacts));
        } else if (matchingContacts.Length == 1) {
            // We have exactly one matching contact
            resolutionResults.Add (INPersonResolutionResult.GetSuccess (recipient));
        } else {
            // We have no contacts matching the description provided
            resolutionResults.Add ((INPersonResolutionResult)INPersonResolutionResult.Unsupported);
        }
    }

    completion (resolutionResults.ToArray ());
}

[Export ("resolveContentForSendMessage:withCompletion:")]
public void ResolveContent (INSendMessageIntent intent, Action<INStringResolutionResult> completion)
{
    var text = intent.Content;
    if (!string.IsNullOrEmpty (text))
        completion (INStringResolutionResult.GetSuccess (text));
    else
        completion ((INStringResolutionResult)INStringResolutionResult.NeedsValue);
}

Per altre informazioni, vedere le informazioni di riferimento sulla fase di risoluzione e le informazioni di riferimento sulle finalità di risoluzione e gestione di Apple.

Gestione della fase di conferma

La fase Confirm (Conferma) è la posizione in cui l'estensione della finalità verifica di avere tutte le informazioni necessarie per soddisfare la richiesta dell'utente. L'app vuole inviare una conferma insieme a tutti i dettagli di supporto di ciò che sta per accadere a Siri in modo che possa essere confermato con l'utente che si tratta dell'azione desiderata.

[Export ("confirmSendMessage:completion:")]
public void ConfirmSendMessage (INSendMessageIntent intent, Action<INSendMessageIntentResponse> completion)
{
    // Verify user is authenticated and the app is ready to send a message.
    ...

    var userActivity = new NSUserActivity (nameof (INSendMessageIntent));
    var response = new INSendMessageIntentResponse (INSendMessageIntentResponseCode.Ready, userActivity);
    completion (response);
}

Per altre informazioni, vedere le informazioni di riferimento sulla fase di conferma.

Elaborazione della finalità

Questo è il punto in cui l'estensione finalità esegue effettivamente l'attività per soddisfare la richiesta dell'utente e passare i risultati a Siri in modo che l'utente possa essere informato.

public void HandleSendMessage (INSendMessageIntent intent, Action<INSendMessageIntentResponse> completion)
{
    // Implement the application logic to send a message here.
    ...

    var userActivity = new NSUserActivity (nameof (INSendMessageIntent));
    var response = new INSendMessageIntentResponse (INSendMessageIntentResponseCode.Success, userActivity);
    completion (response);
}

public void HandleSearchForMessages (INSearchForMessagesIntent intent, Action<INSearchForMessagesIntentResponse> completion)
{
    // Implement the application logic to find a message that matches the information in the intent.
    ...

    var userActivity = new NSUserActivity (nameof (INSearchForMessagesIntent));
    var response = new INSearchForMessagesIntentResponse (INSearchForMessagesIntentResponseCode.Success, userActivity);

    // Initialize with found message's attributes
    var sender = new INPerson (new INPersonHandle ("sarah@example.com", INPersonHandleType.EmailAddress), null, "Sarah", null, null, null);
    var recipient = new INPerson (new INPersonHandle ("+1-415-555-5555", INPersonHandleType.PhoneNumber), null, "John", null, null, null);
    var message = new INMessage ("identifier", "I am so excited about SiriKit!", NSDate.Now, sender, new INPerson [] { recipient });
    response.Messages = new INMessage [] { message };
    completion (response);
}

public void HandleSetMessageAttribute (INSetMessageAttributeIntent intent, Action<INSetMessageAttributeIntentResponse> completion)
{
    // Implement the application logic to set the message attribute here.
    ...

    var userActivity = new NSUserActivity (nameof (INSetMessageAttributeIntent));
    var response = new INSetMessageAttributeIntentResponse (INSetMessageAttributeIntentResponseCode.Success, userActivity);
    completion (response);
}

Per altre informazioni, vedere le informazioni di riferimento sulla fase di gestione.

Aggiunta di un'estensione dell'interfaccia utente intents

L'estensione facoltativa dell'interfaccia utente intenti offre l'opportunità di portare l'interfaccia utente e la personalizzazione dell'app nell'esperienza Siri e rendere gli utenti connessi all'app. Con questa estensione l'app può portare il marchio, oltre che visivo e altre informazioni nella trascrizione.

Esempio di output dell'estensione dell'interfaccia utente intents

Proprio come l'estensione finalità, lo sviluppatore eseguirà il passaggio seguente per l'estensione dell'interfaccia utente intents:

  • Aggiungere un progetto di estensione dell'interfaccia utente intents alla soluzione app Xamarin.iOS.
  • Configurare il file di estensione Info.plist dell'interfaccia utente intents.
  • Modificare la classe principale dell'estensione dell'interfaccia utente intents.

Per altre informazioni, vedere le informazioni di riferimento sull'estensione dell'interfaccia utente intents e Informazioni di riferimento sull'interfaccia personalizzata di Apple.

Creazione dell'estensione

Per aggiungere un'estensione dell'interfaccia utente intents alla soluzione, eseguire le operazioni seguenti:

  1. Fare clic con il pulsante destro del mouse sul nome della soluzione nel riquadro della soluzione e scegliere Aggiungi>nuovo progetto.

  2. Nella finestra di dialogo selezionare iOS Extensions Intent UI Extensions (Estensioni>finalità iOS>) e fare clic sul pulsante Avanti:

    Selezionare l'estensione dell'interfaccia utente finalità

  3. Immettere quindi un nome per l'estensione della finalità e fare clic sul pulsante Avanti :

    Immettere un nome per l'estensione della finalità in Visual Studio per Mac.

  4. Infine, fare clic sul pulsante Crea per aggiungere l'estensione finalità alla soluzione app:

    Aggiungere l'estensione della finalità alla soluzione delle app in Visual Studio per Mac.

  5. Nella Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Riferimenti dell'estensione finalità appena creata. Controllare il nome del progetto comune di libreria di codice condiviso (creato in precedenza dall'app) e fare clic sul pulsante OK :

    Selezionare il nome del progetto comune di libreria di codice condiviso in Visual Studio per Mac.

Configurazione di Info.plist

Configurare il file dell'estensione Info.plist dell'interfaccia utente intents per l'uso con l'app.

Proprio come qualsiasi estensione dell'app tipica, l'app avrà le chiavi esistenti di NSExtension e NSExtensionAttributes. Per un'estensione finalità è presente un nuovo attributo che deve essere configurato:

Un nuovo attributo che deve essere configurato

IntentsSupported è obbligatorio ed è costituito da una matrice di nomi di classe finalità che l'app vuole supportare dall'estensione finalità.

Per configurare il file dell'estensione dell'interfaccia utente finalità, fare doppio clic su di Info.plist esso nel Esplora soluzioni per aprirlo per la modifica. Passare quindi alla visualizzazione Origine , quindi espandere i NSExtension tasti e NSExtensionAttributes nell'editor:

Chiavi NSExtension e NSExtensionAttributes nell'editor.

Espandere la IntentsSupported chiave e aggiungere il nome di qualsiasi classe intenta supportata da questa estensione. Per l'app MonkeyChat di esempio, supporta :INSendMessageIntent

Per un elenco completo dei domini finalità disponibili, vedere Informazioni di riferimento per i domini finalità di Apple.

Configurazione della classe principale

Configurare la classe principale che funge da punto di ingresso principale per l'estensione dell'interfaccia utente finalità in Siri. Deve essere una sottoclasse di UIViewController che è conforme all'interfaccia IINUIHostedViewController . Ad esempio:

using System;
using Foundation;
using CoreGraphics;
using Intents;
using IntentsUI;
using UIKit;

namespace MonkeyChatIntentsUI
{
    public partial class IntentViewController : UIViewController, IINUIHostedViewControlling
    {
        #region Constructors
        protected IntentViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }

        public override void DidReceiveMemoryWarning ()
        {
            // Releases the view if it doesn't have a superview.
            base.DidReceiveMemoryWarning ();

            // Release any cached data, images, etc that aren't in use.
        }
        #endregion

        #region Public Methods
        [Export ("configureWithInteraction:context:completion:")]
        public void Configure (INInteraction interaction, INUIHostedViewContext context, Action<CGSize> completion)
        {
            // Do configuration here, including preparing views and calculating a desired size for presentation.

            if (completion != null)
                completion (DesiredSize ());
        }

        [Export ("desiredSize:")]
        public CGSize DesiredSize ()
        {
            return ExtensionContext.GetHostedViewMaximumAllowedSize ();
        }
        #endregion
    }
}

Siri passerà un'istanza INInteraction di classe al Configure metodo dell'istanza UIViewController all'interno dell'estensione dell'interfaccia utente finalità.

L'oggetto INInteraction fornisce tre informazioni chiave per l'estensione:

  1. Oggetto Intent in fase di elaborazione.
  2. Oggetto Risposta finalità dai Confirm metodi e Handle dell'estensione finalità.
  3. Stato interazione che definisce lo stato dell'interazione tra l'app e Siri.

L'istanza UIViewController è la classe di principio per l'interazione con Siri e perché eredita da UIViewController, ha accesso a tutte le funzionalità di UIKit.

Quando Siri chiama il Configure metodo di UIViewController passa in un contesto di visualizzazione che indica che il controller di visualizzazione sarà ospitato in una scheda Siri Snippit o Maps.

Siri passerà anche un gestore di completamento che l'app deve restituire le dimensioni desiderate della visualizzazione al termine della configurazione dell'app.

Progettare l'interfaccia utente in iOS Designer

Layout dell'interfaccia utente dell'estensione interfaccia utente intents in iOS Designer. Fare doppio clic sul file dell'estensione MainInterface.storyboard nel Esplora soluzioni per aprirlo per la modifica. Trascinare in tutti gli elementi dell'interfaccia utente necessari per compilare l'interfaccia utente e salvare le modifiche.

Importante

Anche se è possibile aggiungere elementi interattivi, UIButtons ad esempio o UITextFields all'estensione dell'interfaccia utente finalità UIViewController, questi sono strettamente vietati perché l'interfaccia utente della finalità in non interattivo e l'utente non sarà in grado di interagire con loro.

Collegare l'interfaccia utente

Con l'interfaccia utente dell'estensione dell'interfaccia utente intents creata in Progettazione iOS, modificare la sottoclasse ed eseguire l'override UIViewController del Configure metodo come indicato di seguito:

[Export ("configureWithInteraction:context:completion:")]
public void Configure (INInteraction interaction, INUIHostedViewContext context, Action<CGSize> completion)
{
    // Do configuration here, including preparing views and calculating a desired size for presentation.
    ...

    // Return desired size
    if (completion != null)
        completion (DesiredSize ());
}

[Export ("desiredSize:")]
public CGSize DesiredSize ()
{
    return ExtensionContext.GetHostedViewMaximumAllowedSize ();
}

Override dell'interfaccia utente di Siri predefinita

L'estensione dell'interfaccia utente Intents verrà sempre visualizzata insieme ad altri contenuti siri, ad esempio l'icona dell'app e il nome nella parte superiore dell'interfaccia utente o, in base alla finalità, i pulsanti (ad esempio Invia o Annulla) possono essere visualizzati nella parte inferiore.

Esistono alcune istanze in cui l'app può sostituire le informazioni visualizzate da Siri all'utente per impostazione predefinita, ad esempio la messaggistica o le mappe in cui l'app può sostituire l'esperienza predefinita con un'esperienza personalizzata per l'app.

Se l'estensione dell'interfaccia utente Intents deve eseguire l'override degli elementi dell'interfaccia utente siri predefinita, la UIViewController sottoclasse dovrà implementare l'interfaccia IINUIHostedViewSiriProviding e acconsentire esplicitamente alla visualizzazione di un particolare elemento di interfaccia.

Aggiungere il codice seguente alla UIViewController sottoclasse per indicare a Siri che l'estensione dell'interfaccia utente finalità sta già visualizzando il contenuto del messaggio:

public bool DisplaysMessage {
    get {return true;}
}

Considerazioni

Apple suggerisce che lo sviluppatore tenga conto delle considerazioni seguenti durante la progettazione e l'implementazione delle estensioni dell'interfaccia utente finalità:

  • Essere consapevoli dell'utilizzo della memoria: poiché le estensioni dell'interfaccia utente delle finalità sono temporanee e visualizzate solo per un breve periodo di tempo, il sistema impone vincoli di memoria più stretti rispetto a quelli usati con un'app completa.
  • Prendere in considerazione le dimensioni minime e massime della visualizzazione: assicurarsi che le estensioni dell'interfaccia utente della finalità siano valide in ogni tipo di dispositivo iOS, dimensioni e orientamento. Inoltre, le dimensioni desiderate che l'app invia a Siri potrebbero non essere in grado di concedere.
  • Usa modelli di layout flessibili e adattivi: ancora una volta, per assicurarti che l'interfaccia utente sia ottimale in ogni dispositivo.

Riepilogo

Questo articolo ha illustrato SiriKit e come può essere aggiunto alle app Xamarin.iOS per fornire servizi accessibili all'utente usando Siri e l'app Mappe in un dispositivo iOS.