Implementación de SiriKit en Xamarin.iOS
En este artículo se describen los pasos necesarios para implementar la compatibilidad con SiriKit en aplicaciones de Xamarin.iOS.
Novedad de iOS 10, SiriKit permite que una aplicación Xamarin.iOS proporcione servicios accesibles para el usuario mediante Siri y la aplicación Maps en un dispositivo iOS. En este artículo se describen los pasos necesarios para implementar la compatibilidad con SiriKit en las aplicaciones de Xamarin.iOS agregando las extensiones de intenciones necesarias, extensiones de interfaz de usuario de intenciones y vocabulario.
Siri funciona con el concepto de Dominios, grupos de acciones de conocimiento para tareas relacionadas. Cada interacción de la aplicación con Siri debe incluirse en uno de sus dominios de servicio de la siguiente manera:
- Llamadas de audio o vídeo.
- Reservar un viaje.
- Administrar entrenamientos.
- Mensajería.
- Buscar fotos.
- Enviar o recibir pagos.
Cuando el usuario realiza una solicitud de Siri que implica uno de los servicios de la extensión de aplicación, SiriKit envía a la extensión un objeto Intent que describe la solicitud del usuario junto con los datos auxiliares. A continuación, la extensión de aplicación genera el objeto Response adecuado para laIntención dado, que detalla cómo la extensión puede controlar la solicitud.
En esta guía se presenta un ejemplo rápido de cómo incluir compatibilidad con SiriKit en una aplicación existente. Para este ejemplo, usaremos la aplicación MonkeyChat falsa:
MonkeyChat mantiene su propio libro de contactos de los amigos del usuario, cada uno asociado a un nombre de pantalla (como Bobo, por ejemplo), y permite al usuario enviar chats de texto a cada amigo por su nombre de pantalla.
Extensión de la aplicación con SiriKit
Como se muestra en la guía de Descripción de los conceptos de SiriKit, hay tres partes principales implicadas en la extensión de una aplicación con SiriKit:
Entre ellas se incluyen las siguientes:
- Extensión Intents: Comprueba las respuestas de los usuarios, confirma que la aplicación puede controlar la solicitud y realiza realmente la tarea para cumplir la solicitud del usuario.
- Extensión de interfaz de usuario de Intents - Opcional, proporciona una interfaz de usuario personalizada a las respuestas en el entorno de Siri y puede llevar la interfaz de usuario de las aplicaciones y la personalización de marca a Siri para enriquecer la experiencia del usuario.
- Aplicación: Proporciona a la aplicación vocabularios específicos del usuario para ayudar a Siri a trabajar con ella.
Todos estos elementos y los pasos para incluirlos en la aplicación se tratarán en detalle en las secciones siguientes.
Preparación de la aplicación
SiriKit se basa en Extensiones, sin embargo, antes de agregar extensiones a la aplicación, hay algunas cosas que el desarrollador debe hacer para ayudar con la adopción de SiriKit.
Mover código compartido común
En primer lugar, el desarrollador puede mover parte del código común que se compartirá entre la aplicación y las extensiones en Proyectos compartidos, Bibliotecas de clases portables (PCL) o Bibliotecas nativas.
Las extensiones deberán poder hacer todas las cosas que hace la aplicación. En términos de la aplicación MonkeyChat de ejemplo, cosas como buscar contactos, agregar nuevos contactos, enviar mensajes y recuperar el historial de mensajes.
Al mover este código común a un proyecto compartido, PCL o biblioteca nativa, facilita el mantenimiento de ese código en un lugar común y garantiza que la extensión y la aplicación primaria proporcionan experiencias y funcionalidades uniformes para el usuario.
En el caso de la aplicación de ejemplo MonkeyChat, los modelos de datos y el código de procesamiento, como el acceso a la red y la base de datos, se moverán a una Biblioteca nativa.
Haga lo siguiente:
Inicie Visual Studio para Mac y abra la aplicación MonkeyChat.
Haga clic con el botón derecho en el nombre de la solución en el Panel de solución y seleccione Agregar>Nuevo proyecto...:
SeleccioneiOS>Biblioteca>Biblioteca de clases y haga clic en el botón Siguiente:
Escriba
MonkeyChatCommon
para el Nombre y haga clic en el botón Crear:Haga clic con el botón derecho en la carpeta Referencias de la aplicación principal en el Explorador de soluciones y seleccione Editar referencias.... Compruebe el proyecto MonkeyChatCommon y haga clic en el botón Aceptar:
En el Explorador de soluciones, arrastre el código compartido común desde la aplicación principal a la Biblioteca nativa.
En el caso de MonkeyChat, arrastre las carpetas DataModels y Procesadores desde la aplicación principal a la biblioteca nativa:
Edite cualquiera de los archivos que se movieron a la biblioteca nativa y cambie el espacio de nombres para que coincida con el de la biblioteca. Por ejemplo, al cambiar 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 ()
{
}
...
}
}
A continuación, vuelva a la aplicación principal y agregue una instrucción using
para el espacio de nombres de la biblioteca nativa en cualquier lugar donde la aplicación use una de las clases que se han movido:
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;
...
}
}
Diseño de la aplicación para extensiones
Normalmente, una aplicación se registrará para varias intenciones y el desarrollador debe asegurarse de que la aplicación está diseñada para el número adecuado de extensiones de intención.
En la situación en la que una aplicación requiere más de una intención, el desarrollador tiene la opción de colocar todo su control de intenciones en una extensión de intención o crear una extensión de intención independiente para cada intención.
Si elige crear una extensión de intención independiente para cada intención, el desarrollador podría terminar duplicando una gran cantidad de código reutilizable en cada extensión y crear una gran cantidad de sobrecarga de procesador y memoria.
Para ayudar a elegir entre las dos opciones, vea si alguna de las intenciones pertenece de forma natural. Por ejemplo, una aplicación que realizó llamadas de audio y vídeo podría querer incluir ambas intenciones en una sola extensión de intención, ya que administran tareas similares y podrían proporcionar la mayor reutilización del código.
Para cualquier intención o grupo de intenciones que no se ajusten a un grupo existente, cree una nueva extensión de intención en la solución de la aplicación para contenerlas.
Establecimiento de los derechos necesarios
Cualquier aplicación de Xamarin.iOS que incluya la integración de SiriKit debe tener establecidos los derechos correctos. Si el desarrollador no establece correctamente estos derechos necesarios, no podrá instalar ni probar la aplicación en hardware real de iOS 10 (o superior), que también es necesario, ya que el simulador de iOS 10 no es compatible con SiriKit.
Haga lo siguiente:
Haga doble clic en el archivo
Entitlements.plist
en el Explorador de soluciones para abrirlo para su edición.Cambie a la pestaña Source (Origen).
Agregue la
com.apple.developer.siri
propiedad , establezca el tipo enBoolean
y el valor enYes
:Guarde los cambios en el archivo.
Haga doble clic en el Archivo de proyecto en el Explorador de soluciones para abrirlo para su edición.
Seleccione Firma de lotes de iOS y asegúrese de que el archivo
Entitlements.plist
esté seleccionado en el campo Derechos personalizados:Haga clic en el botón Aceptar para guardar los cambios.
Cuando termine, el archivo Entitlements.plist
de la aplicación debe tener un aspecto similar al siguiente (abierto en un editor externo):
<?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>
Aprovisionamiento correcto de la aplicación
Debido a la estricta seguridad que Apple ha colocado alrededor del marco SiriKit, cualquier aplicación de Xamarin.iOS que implemente SiriKit debe tener el identificador de aplicación y los derechos correctos (vea la sección anterior) y debe estar firmado con un perfil de aprovisionamiento adecuado.
Haga lo siguiente en el equipo Mac:
En un explorador web, vaya a https://developer.apple.com e inicie sesión en su cuenta.
Haga clic en Certificados, Identificadores y Perfiles.
Seleccione Perfiles de aprovisionamiento y seleccione Identificadores de aplicación, y a continuación, haga clic en el + botón.
Escriba un Nombre para el nuevo perfil.
Escriba un Id. de lote siguiendo la recomendación de nomenclatura de Apple.
Desplácese hacia abajo hasta la sección App Services, seleccione SiriKit y haga clic en el botón Continuar:
Compruebe toda la configuración y, a continuación, Enviar el identificador de la aplicación.
Seleccione Perfiles de aprovisionamiento>Desarrollo, haga clic en el botón +, seleccione el Id. de Apple, y haga clic en Continuar.
Haga clic en Seleccionar Todo, y a continuación, haga clic en Continuar.
Haga clic en Seleccionar todo de nuevo y, a continuación, haga clic en Continuar.
Escriba un Nombre de perfil con sugerencias de nomenclatura de Apple y haga clic en Continuar.
Inicie Xcode.
En el menú Xcode, seleccione Preferencias…
Seleccione Cuentas, y haga clic en el botón Ver detalles… :
Haga clic en el Descargar todos los perfiles Botón en la esquina inferior izquierda:
Asegúrese de que el Perfil de aprovisionamiento creado anteriormente se ha instalado en Xcode.
Abra el proyecto para agregar compatibilidad con SiriKit a en Visual Studio para Mac.
Haga doble clic en el
Info.plist
archivo en elExplorador de soluciones.Asegúrese de que el Identificador de agrupación coincide con el creado en el Portal para desarrolladores de Apple anterior:
En el Explorador de soluciones, seleccione Proyecto.
Haga clic con el botón derecho en el proyecto y seleccione Opciones.
Seleccione Firma de paquetes de iOS, seleccione la Identidad de firma y Perfil de aprovisionamiento creado anteriormente:
Haga clic en el botón Aceptar para guardar los cambios.
Importante
Probar SiriKit solo funciona en un dispositivo de hardware iOS 10 real y no en el simulador de iOS 10. Si tiene problemas al instalar una aplicación de Xamarin.iOS habilitada para SiriKit en hardware real, asegúrese de que los derechos necesarios, el identificador de aplicación, el identificador de firma y el perfil de aprovisionamiento se han configurado correctamente en el Portal para desarrolladores de Apple y Visual Studio para Mac.
Solicitud de autorización de Siri
Antes de que la aplicación agregue cualquier vocabulario específico del usuario o las extensiones de intenciones se conecta a Siri, debe solicitar autorización del usuario para acceder a Siri.
Edite el archivo de Info.plist
la aplicación, cambie a la vista Origen y agregue la NSSiriUsageDescription
clave con un valor de cadena que describa cómo usará Siri y qué tipos de datos se enviarán. Por ejemplo, la aplicación MonkeyChat podría decir "Los contactos de MonkeyChat se enviarán a Siri":
Llame al RequestSiriAuthorization
método de la INPreferences
clase cuando se inicie la aplicación por primera vez. Edite el archivo AppDelegate.cs
y haga que el método FinishedLaunching
se parezca a lo siguiente:
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 primera vez que se llama a este método, se muestra una alerta que solicita al usuario que permita que la aplicación acceda a Siri. El mensaje que el desarrollador agregó al NSSiriUsageDescription
anterior se mostrará en esta alerta. Si el usuario deniega inicialmente el acceso, puede usar la aplicación Configuración para conceder acceso a la aplicación.
En cualquier momento, la aplicación puede comprobar la capacidad de la aplicación para acceder a Siri llamando al SiriAuthorizationStatus
método de la INPreferences
clase.
Localización y Siri
En un dispositivo iOS, el usuario puede seleccionar un idioma para Siri diferente y, a continuación, el valor predeterminado del sistema. Al trabajar con datos localizados, la aplicación deberá usar el SiriLanguageCode
método de la INPreferences
clase para obtener el código de idioma de Siri. Por ejemplo:
var language = INPreferences.SiriLanguageCode();
// Take action based on language
if (language == "en-US") {
// Do something...
}
Agregar vocabulario específico del usuario
El vocabulario específico del usuario va a proporcionar palabras o frases exclusivas de usuarios individuales de la aplicación. Estos se proporcionarán en tiempo de ejecución desde la aplicación principal (no las extensiones de aplicación) como un conjunto ordenado de términos, ordenados en una prioridad de uso más significativa para los usuarios, con los términos más importantes al principio de la lista.
Vocabulario específico del usuario debe pertenecer a una de las siguientes categorías:
- Nombres de contacto (no administrados por el marco de contactos).
- Etiquetas de fotos.
- Nombres de álbumes de fotos.
- Nombres de entrenamiento.
Al seleccionar terminología para registrarse como vocabulario personalizado, solo elija términos que alguien no conozca la aplicación podría malinterpretar. Nunca registre términos comunes como "Mi entrenamiento" o "Mi álbum". Por ejemplo, la aplicación MonkeyChat registrará los alias asociados a cada contacto en la libreta de direcciones del usuario.
La aplicación proporciona el vocabulario específico del usuario llamando al SetVocabularyStrings
método de la INVocabulary
clase y pasando una NSOrderedSet
colección desde la aplicación principal. La aplicación siempre debe llamar al RemoveAllVocabularyStrings
método primero para quitar los términos existentes antes de agregar otros nuevos. Por ejemplo:
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 este código en su lugar, podría llamarse de la siguiente manera:
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 trata el vocabulario personalizado como sugerencias e incorporará la mayor parte de la terminología posible. Sin embargo, el espacio para vocabulario personalizado es limitado, lo que hace que sea importante registrar solo la terminología que podría resultar confusa, por lo que se mantiene el número total de términos registrados en un mínimo.
Para obtener más información, vea nuestra Referencia de vocabulario específico del usuario y la Especificación de referencia de vocabulario personalizado de Apple.
Agregar vocabulario específico de la aplicación
El vocabulario específico de la aplicación define las palabras y frases específicas que conocerán todos los usuarios de la aplicación, como tipos de vehículo o nombres de entrenamiento. Dado que forman parte de la aplicación, se definen en un archivo AppIntentVocabulary.plist
como parte del lote de aplicaciones principal. Además, estas palabras y frases deben localizarse.
Los términos de vocabulario específicos de la aplicación deben pertenecer a una de las siguientes categorías:
- Opciones de paseo.
- Nombres de entrenamiento.
El archivo de vocabulario específico de la aplicación contiene dos claves de nivel raíz:
ParameterVocabularies
Obligatorio: define los términos personalizados de la aplicación y los parámetros de intención a los que se aplican.IntentPhrases
Opcional: contiene frases de ejemplo mediante los términos personalizados definidos en .ParameterVocabularies
Cada entrada en el ParameterVocabularies
debe especificar una cadena de identificador, un término y la intención a la que se aplica el término. Además, un único término se puede aplicar a varias intenciones.
Para obtener una lista completa de los valores aceptables y la estructura de archivos requerida, vea Referencia del formato de archivo de vocabulario de la aplicación de Apple.
Para agregar un archivo AppIntentVocabulary.plist
al proyecto de aplicación, haga lo siguiente:
Haga clic con el botón derecho en el nombre del proyecto en el Explorador de soluciones y seleccione Agregar>Nuevo archivo...>iOS:
Haga doble clic en el archivo
AppIntentVocabulary.plist
en el Explorador de soluciones para abrirlo para su edición.Haga clic en el + para agregar una clave, establezca el Nombre en
ParameterVocabularies
y el Tipo enArray
:Expanda
ParameterVocabularies
y haga clic en el + botón y establezca el Tipo enDictionary
:Haga clic en el + para agregar una nueva clave, establezca el Nombre en
ParameterNames
y el Tipo enArray
:Haga clic en el + para agregar una nueva clave con el Tipo de
String
y el valor como uno de los nombres de parámetro disponibles. Por ejemplo,INStartWorkoutIntent.workoutName
:Agregue la clave de
ParameterVocabulary
a la clave deParameterVocabularies
con el Tipo deArray
:Agregue una nueva clave con el Tipo de
Dictionary
:Agregue la
VocabularyItemIdentifier
clave con el Tipo deString
y especifique un identificador único para el término:Agregue la
VocabularyItemSynonyms
clave con el Tipo deArray
:Agregue una nueva clave con el Tipo de
Dictionary
:Agregue la
VocabularyItemPhrase
clave con el Tipo deString
y el término que define la aplicación:Agregue la
VocabularyItemPronunciation
clave con el Tipo deString
y la pronunciación fonética del término:Agregue la
VocabularyItemExamples
clave con el Tipo deArray
:Agregue algunas
String
claves con usos de ejemplo del término :Repita los pasos anteriores para cualquier otro término personalizado que necesite definir la aplicación.
Contraiga la
ParameterVocabularies
clave.Agregue la
IntentPhrases
clave con el Tipo deArray
:Agregue una nueva clave con el Tipo de
Dictionary
:Agregue la
IntentName
clave con el Tipo deString
y la intención para el ejemplo:Agregue la
IntentExamples
clave con el Tipo deArray
:Agregue algunas
String
claves con usos de ejemplo del término :Repita los pasos anteriores para cualquier intención de la aplicación que necesite para proporcionar un ejemplo de uso.
Importante
El AppIntentVocabulary.plist
se registrará con Siri en los dispositivos de prueba durante el desarrollo y puede tardar algún tiempo en incorporar el vocabulario personalizado. Como resultado, el evaluador tendrá que esperar varios minutos antes de intentar probar vocabulario específico de la aplicación cuando se haya actualizado.
Para obtener más información, vea nuestra Referencia de vocabulario específico de la aplicación y la Referencia de vocabulario personalizado de Apple.
Agregar una extensión de intenciones
Ahora que la aplicación se ha preparado para adoptar SiriKit, el desarrollador tendrá que agregar una (o varias) extensiones de intenciones a la solución para controlar las intenciones necesarias para la integración de Siri.
Para cada extensión de intenciones necesaria, haga lo siguiente:
- Agregue un proyecto de extensión de intenciones a la solución de aplicación de Xamarin.iOS.
- Configure el archivo de extensión
Info.plist
de intenciones. - Modifique la clase principal de la extensión de intenciones.
Para obtener más información, vea nuestra Referencia sobre la extensión de intenciones y la Referencia de creación de la extensión de intenciones de Apple.
Creación de la extensión
Para agregar una extensión de intención a la solución, haga lo siguiente:
Haga clic con el botón derecho en el Nombre de la solución en el Panel de solución y seleccione Agregar>Agregar nuevo proyecto....
En el cuadro de diálogo, seleccione iOS>Extensiones>Extensión de intención y haga clic en el botón Siguiente:
A continuación, escriba un Nombre para la extensión de intención y haga clic en el botón Siguiente:
Por último, haga clic en el botón Crear para agregar la extensión de intención a la solución de aplicaciones:
En el Explorador de soluciones, haga clic con el botón derecho en la carpeta Referencias de la extensión de intención recién creada. Compruebe el nombre del proyecto de biblioteca de código compartido común (que la aplicación creada anteriormente) y haga clic en el botón Aceptar:
Repita estos pasos para el número de extensiones de intención (basadas en Arquitectura de la aplicación para extensiones sección anterior) que necesitará la aplicación.
Configuración de Info.plist
Para cada una de las extensiones de intenciones que se han agregado a la solución de la aplicación, debe configurarse en los archivos Info.plist
para que funcionen con la aplicación.
Al igual que cualquier extensión de aplicación típica, la aplicación tendrá las claves existentes de NSExtension
y NSExtensionAttributes
. Para una extensión de intención hay dos atributos nuevos que se deben configurar:
- IntentsSupported: Es necesario y consta de una matriz de nombres de clase de intención que la aplicación quiere admitir desde la extensión de intención.
- IntentsRestrictedWhileLocked: Es una clave opcional para que la aplicación especifique el comportamiento de la pantalla de bloqueo de la extensión. Consta de una matriz de nombres de clase de intención que la aplicación quiere requerir que el usuario inicie sesión para usarlo desde la extensión de intención.
Para configurar el archivo de Info.plist
la extensión de intención, haga doble clic en él en el Explorador de soluciones para abrirlo para su edición. A continuación, cambie a la vista Origen y expanda las NSExtension
claves y NSExtensionAttributes
en el editor:
Expanda la clave IntentsSupported
y agregue el nombre de cualquier clase de intención que admita esta extensión. Para la aplicación MonkeyChat de ejemplo, admite el INSendMessageIntent
:
Si la aplicación requiere que el usuario inicie sesión en el dispositivo para usar una intención determinada, expanda la clave IntentRestrictedWhileLocked
y agregue los nombres de clase de las intenciones que tienen acceso restringido. Para la aplicación MonkeyChat de ejemplo, el usuario debe iniciar sesión para enviar un mensaje de chat, por lo que hemos agregado INSendMessageIntent
:
Para obtener una lista completa de los dominios de intención disponibles, vea Referencia de dominios de intención de Apple.
Configuración de la clase Main
A continuación, el desarrollador deberá configurar la clase principal que actúa como punto de entrada principal para la extensión de intención en Siri. Debe ser una subclase de INExtension
la que se ajusta al IINIntentHandler
delegado. Por ejemplo:
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
...
}
}
Hay un método solitario que la aplicación debe implementar en la clase principal Extensión de intención, el GetHandler
método. SiriKit pasa este método y la aplicación debe devolver un Controlador de intencionesque coincida con el tipo de la intención especificada.
Dado que la aplicación MonkeyChat de ejemplo solo controla una intención, se devuelve en el GetHandler
método. Si la extensión controla más de una intención, el desarrollador agregaría una clase para cada tipo de intención y devolvería una instancia aquí basada en el Intent
pasado al método.
Control de la fase de resolución
La fase de resolución es donde la extensión de intención aclarará y validará los parámetros pasados desde Siri y se han establecido a través de la conversación del usuario.
Para cada parámetro que se envía desde Siri, hay un Resolve
método. La aplicación tendrá que implementar este método para cada parámetro que la aplicación pueda necesitar la ayuda de Siri para obtener la respuesta correcta del usuario.
En el caso de la aplicación MonkeyChat de ejemplo, la extensión de intención requerirá que uno o varios destinatarios envíen el mensaje. Para cada destinatario de la lista, la extensión tendrá que realizar una búsqueda de contactos que pueda tener el siguiente resultado:
- Se encuentra exactamente un contacto coincidente.
- Se encuentran dos o más contactos coincidentes.
- No se encuentra ningún contacto coincidente.
Además, MonkeyChat requiere contenido para el cuerpo del mensaje. Si el usuario no lo ha proporcionado, Siri debe solicitar al usuario el contenido.
La extensión de intención tendrá que controlar correctamente cada uno de estos casos.
[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);
}
Para obtener más información, vea nuestra Referencia de la fase de resolución y la Referencia de intenciones de resolución y control de Apple.
Control de la fase de confirmación
La fase confirmar es donde la extensión de intención comprueba que tiene toda la información para satisfacer la solicitud del usuario. La aplicación quiere enviar confirmación a lo largo de todos los detalles auxiliares de lo que está a punto de pasar a Siri para que se pueda confirmar con el usuario que se trata de la acción prevista.
[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);
}
Para obtener más información, vea nuestra Referencia de la fase de confirmación.
Procesamiento de la intención
Este es el punto en el que la extensión de intención realiza realmente la tarea para cumplir la solicitud del usuario y pasar los resultados a Siri para que el usuario pueda ser informado.
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);
}
Para obtener más información, vea nuestra Referencia de fase de control.
Agregar una extensión de interfaz de usuario de intenciones
La extensión opcional de interfaz de usuario de intenciones presenta la oportunidad de incorporar la interfaz de usuario y la personalización de marca de la aplicación a la experiencia de Siri y hacer que los usuarios se sientan conectados a la aplicación. Con esta extensión, la aplicación puede traer la marca, así como visual y otra información a la transcripción.
Al igual que la extensión Intents, el desarrollador realizará el siguiente paso para la extensión de interfaz de usuario de intención:
- Agregue un proyecto de extensión de interfaz de usuario intenciones a la solución de aplicación de Xamarin.iOS.
- Configure el archivo de extensión de interfaz de usuario de intenciones
Info.plist
. - Modifique la clase principal de extensión de interfaz de usuario de intenciones.
Para obtener más información, vea nuestra Referencia de la extensión de interfaz de usuario de intenciones y la Referencia de creación de interfaces personalizadas de Apple.
Creación de la extensión
Para agregar una extensión de interfaz de usuario de intenciones a la solución, haga lo siguiente:
Haga clic con el botón derecho en el Nombre de la solución en el Panel de solución y seleccione Agregar>Agregar nuevo proyecto....
En el cuadro de diálogo, seleccione iOS>Extensiones>Extensión de interfaz de usuario de intención y haga clic en el botón Siguiente:
A continuación, escriba un Nombre para la extensión de intención y haga clic en el botón Siguiente:
Por último, haga clic en el botón Crear para agregar la extensión de intención a la solución de aplicaciones:
En el Explorador de soluciones, haga clic con el botón derecho en la carpeta Referencias de la extensión de intención recién creada. Compruebe el nombre del proyecto de biblioteca de código compartido común (que la aplicación creada anteriormente) y haga clic en el botón Aceptar:
Configuración de Info.plist
Configure el archivo Info.plist
de la extensión interfaz de usuario de intenciones para que funcione con la aplicación.
Al igual que cualquier extensión de aplicación típica, la aplicación tendrá las claves existentes de NSExtension
y NSExtensionAttributes
. Para una extensión de intenciones hay un nuevo atributo que debe configurarse:
IntentsSupported es necesaria y consta de una matriz de nombres de clase de intención que la aplicación quiere admitir desde la extensión de intención.
Para configurar el archivo de laInfo.plist
extensión de interfaz de usuario de intenciones, haga doble clic en él en el Explorador de soluciones para abrirlo para su edición. A continuación, cambie a la vista Origen y expanda las NSExtension
claves y NSExtensionAttributes
en el editor:
Expanda la clave IntentsSupported
y agregue el nombre de cualquier clase de intención que admita esta extensión. Para la aplicación MonkeyChat de ejemplo, admite el INSendMessageIntent
:
Para obtener una lista completa de los dominios de intención disponibles, vea Referencia de dominios de intención de Apple.
Configuración de la clase Main
Configure la clase principal que actúa como punto de entrada principal para la extensión de interfaz de usuario de intención en Siri. Debe ser una subclase de UIViewController
la que se ajusta a la IINUIHostedViewController
interfaz. Por ejemplo:
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 pasará una instancia de clase INInteraction
al método Configure
de la instancia de UIViewController
dentro de la extensión de interfaz de usuario de intención.
El INInteraction
objeto proporciona tres fragmentos clave de información a la extensión:
- Objeto de intención que se está procesando.
- Objeto Intent Response de los métodos
Confirm
yHandle
de la extensión de intención. - Estado de interacción que define el estado de la interacción entre la aplicación y Siri.
La UIViewController
instancia es la clase principal para la interacción con Siri y porque hereda de UIViewController
, tiene acceso a todas las características de UIKit.
Cuando Siri llama al Configure
método de que UIViewController
pasa en un contexto de vista que indica que el controlador de vista se hospedará en un Snippit de Siri o Tarjeta Maps.
Siri también pasará un controlador de finalización que la aplicación necesita para devolver el tamaño deseado de la vista una vez que la aplicación haya terminado de configurarla.
Diseño de la interfaz de usuario en iOS Designer
Diseño de la interfaz de usuario de la extensión de interfaz de usuario de intenciones en iOS Designer. Haga doble clic en el archivoMainInterface.storyboard
de la extensión en el Explorador de soluciones para abrirlo para su edición. Arrastre todos los elementos de interfaz de usuario necesarios para compilar la interfaz de usuario y guardar los cambios.
Importante
Aunque es posible agregar elementos interactivos como UIButtons
o UITextFields
al UIViewController
de la extensión UI de intenciones, estos están estrictamente prohibidos, ya que UI de intenciones no es interactiva y el usuario no podrá interactuar con ellos.
Conexión de la interfaz de usuario
Con la interfaz de usuario de la extensión de interfaz de usuario de intenciones creada en iOS Designer, edite la subclase UIViewController
e invalide el método Configure
de la siguiente manera:
[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 ();
}
Invalidación de la interfaz de usuario de Siri predeterminada
La extensión UI de intenciones siempre se mostrará junto con otro contenido de Siri, como el icono de la aplicación y el nombre en la parte superior de la interfaz de usuario o, en función de la Intención, se pueden mostrar botones (como Enviar o Cancelar) en la parte inferior.
Hay algunas instancias en las que la aplicación puede reemplazar la información que Siri muestra al usuario de forma predeterminada, como la mensajería o los mapas en los que la aplicación puede reemplazar la experiencia predeterminada por una adaptada a la aplicación.
Si la extensión de interfaz de usuario de intenciones necesita invalidar elementos de la interfaz de usuario de Siri predeterminada, la UIViewController
subclase tendrá que implementar la IINUIHostedViewSiriProviding
interfaz y participar para mostrar un elemento de interfaz determinado.
Agregue el código siguiente a la subclase UIViewController
para indicar a Siri que la extensión de la interfaz de usuario de intención ya muestra el contenido del mensaje:
public bool DisplaysMessage {
get {return true;}
}
Consideraciones
Apple sugiere que el desarrollador tenga en cuenta las siguientes consideraciones al diseñar e implementar las extensiones de interfaz de usuario de intención:
- Ser consciente del uso de memoria: Dado que las extensiones de interfaz de usuario de intención son temporales y solo se muestran durante un breve tiempo, el sistema impone restricciones de memoria más estrictas de las que se usan con una aplicación completa.
- Considere los tamaños de vista mínimo y máximo: Asegúrese de que las extensiones de interfaz de usuario de intención tienen un aspecto correcto en cada tipo de dispositivo iOS, tamaño y orientación. Además, es posible que no se pueda conceder el tamaño deseado que la aplicación envía a Siri.
- Usar patrones de diseño flexibles y adaptables: De nuevo, para asegurarse de que la interfaz de usuario sea excelente en todos los dispositivos.
Resumen
En este artículo se ha tratado SiriKit y se ha mostrado cómo se puede agregar a las aplicaciones de Xamarin.iOS para proporcionar servicios accesibles para el usuario mediante Siri y la aplicación Maps en un dispositivo iOS.