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:
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:
tra cui:
- 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.
- 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.
- 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:
Avviare Visual Studio per Mac e aprire l'app MonkeyChat.
Fare clic con il pulsante destro del mouse sul nome della soluzione nel riquadro della soluzione e scegliere Aggiungi>nuovo progetto...:
Selezionare Libreria di classi libreria> iOS>e fare clic sul pulsante Avanti:
Immettere
MonkeyChatCommon
per Nome e fare clic sul pulsante Crea :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:
Nella Esplora soluzioni trascinare il codice condiviso comune dall'app principale alla libreria nativa.
Nel caso di MonkeyChat, trascinare le cartelle DataModels e Processors dall'app principale in Native Library:
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:
Fare doppio clic sul
Entitlements.plist
file nel Esplora soluzioni per aprirlo per la modifica.Passare alla scheda Origine.
Aggiungere la
com.apple.developer.siri
proprietà , impostare Type suBoolean
e Value suYes
:Salvare le modifiche apportate al file.
Fare doppio clic sul file di progetto nel Esplora soluzioni per aprirlo per la modifica.
Selezionare Firma bundle iOS e assicurarsi che il
Entitlements.plist
file sia selezionato nel campo Diritti personalizzati: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:
In un Web browser passare a e accedere all'account https://developer.apple.com .
Fare clic su Certificati, identificatori e profili.
Selezionare Profili di provisioning e selezionare ID app, quindi fare clic sul + pulsante .
Immettere un nome per il nuovo profilo.
Immettere un ID bundle seguendo la raccomandazione di denominazione di Apple.
Scorrere verso il basso fino alla sezione servizio app s, selezionare SiriKit e fare clic sul pulsante Continua:
Verificare tutte le impostazioni, quindi Inviare l'ID app.
Selezionare Provisioning Profiles Development (Sviluppo profili>di provisioning), fare clic sul + pulsante , selezionare l'ID Apple e quindi fare clic su Continua.
Fare clic su Seleziona tutto, quindi su Continua.
Fare di nuovo clic su Seleziona tutto , quindi su Continua.
Immettere un nome profilo usando i suggerimenti di denominazione di Apple, quindi fare clic su Continua.
Avviare Xcode.
Dal menu Xcode selezionare Preferenze...
Selezionare Account, quindi fare clic sul pulsante Visualizza dettagli...
Fare clic sul pulsante Scarica tutti i profili nell'angolo inferiore sinistro:
Verificare che il profilo di provisioning creato in precedenza sia stato installato in Xcode.
Aprire il progetto per aggiungere il supporto di SiriKit a in Visual Studio per Mac.
Fare doppio clic sul
Info.plist
file nel Esplora soluzioni.Assicurarsi che l'identificatore del bundle corrisponda a quello creato nel portale per sviluppatori di Apple precedente:
Nella Esplora soluzioni selezionare il progetto.
Fare clic con il pulsante destro del mouse sul progetto e scegliere Opzioni.
Selezionare Firma bundle iOS, selezionare l'identità di firma e il profilo di provisioning creati in precedenza:
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":
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:
ParameterVocabularies
Obbligatorio: definisce i termini personalizzati dell'app e i parametri delle finalità a cui si applicano.IntentPhrases
Facoltativo: contiene frasi di esempio che usano i termini personalizzati definiti inParameterVocabularies
.
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:
Fare clic con il pulsante destro del mouse sul nome del progetto nella Esplora soluzioni e scegliere Aggiungi>nuovo file...>iOS:
Fare doppio clic sul
AppIntentVocabulary.plist
file nel Esplora soluzioni per aprirlo per la modifica.Fare clic su + per aggiungere una chiave, impostare Il nome su
ParameterVocabularies
e Tipo suArray
:Espandere
ParameterVocabularies
e fare clic sul + pulsante e impostare Il tipo suDictionary
:Fare clic su + per aggiungere una nuova chiave, impostare Il nome su
ParameterNames
e Tipo suArray
: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
:Aggiungere la
ParameterVocabulary
chiave allaParameterVocabularies
chiave con il tipo diArray
:Aggiungere una nuova chiave con il tipo di
Dictionary
:Aggiungere la
VocabularyItemIdentifier
chiave con il tipo diString
e specificare un ID univoco per il termine:Aggiungere la
VocabularyItemSynonyms
chiave con il tipo diArray
:Aggiungere una nuova chiave con il tipo di
Dictionary
:Aggiungere la
VocabularyItemPhrase
chiave con il tipo diString
e il termine che l'app definisce:Aggiungere la
VocabularyItemPronunciation
chiave con il tipo diString
e la pronuncia fonetica del termine:Aggiungere la
VocabularyItemExamples
chiave con il tipo diArray
:Aggiungere alcune
String
chiavi con usi di esempio del termine :Ripetere i passaggi precedenti per qualsiasi altro termine personalizzato che l'app deve definire.
Comprimere la
ParameterVocabularies
chiave.Aggiungere la
IntentPhrases
chiave con il tipo diArray
:Aggiungere una nuova chiave con il tipo di
Dictionary
:Aggiungere la
IntentName
chiave con il tipo diString
e la finalità per l'esempio:Aggiungere la
IntentExamples
chiave con il tipo diArray
:Aggiungere alcune
String
chiavi con usi di esempio del termine :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:
Fare clic con il pulsante destro del mouse sul nome della soluzione nel riquadro della soluzione e scegliere Aggiungi>nuovo progetto.
Nella finestra di dialogo selezionare Estensioni estensioni iOS>Estensioni> finalità e fare clic sul pulsante Avanti:
Immettere quindi un nome per l'estensione della finalità e fare clic sul pulsante Avanti :
Infine, fare clic sul pulsante Crea per aggiungere l'estensione finalità alla soluzione app:
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 :
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:
- 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.
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:
Fare clic con il pulsante destro del mouse sul nome della soluzione nel riquadro della soluzione e scegliere Aggiungi>nuovo progetto.
Nella finestra di dialogo selezionare iOS Extensions Intent UI Extensions (Estensioni>finalità iOS>) e fare clic sul pulsante Avanti:
Immettere quindi un nome per l'estensione della finalità e fare clic sul pulsante Avanti :
Infine, fare clic sul pulsante Crea per aggiungere l'estensione finalità alla soluzione app:
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 :
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:
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:
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:
- Oggetto Intent in fase di elaborazione.
- Oggetto Risposta finalità dai
Confirm
metodi eHandle
dell'estensione finalità. - 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.