Implementando o SiriKit no Xamarin.iOS
Este artigo aborda as etapas necessárias para implementar o suporte ao SiriKit em aplicativos Xamarin.iOS.
Novidade no iOS 10, o SiriKit permite que um aplicativo Xamarin.iOS forneça serviços acessíveis ao usuário usando a Siri e o aplicativo Mapas em um dispositivo iOS. Este artigo aborda as etapas necessárias para implementar o suporte ao SiriKit nos aplicativos Xamarin.iOS adicionando as Extensões de Intenções, Extensões de Interface do Usuário de Intenções e Vocabulário necessários.
A Siri trabalha com o conceito de Domínios, grupos de ações conhecidas para tarefas relacionadas. Cada interação que o aplicativo tem com a Siri deve se enquadrar em um de seus domínios de serviço conhecidos da seguinte maneira:
- Chamadas de áudio ou vídeo.
- Reservando uma viagem.
- Gerenciando treinos.
- Mensagens.
- Pesquisando fotos.
- Envio ou recebimento de pagamentos.
Quando o usuário faz uma solicitação à Siri envolvendo um dos serviços da Extensão de Aplicativo, o SiriKit envia à extensão um objeto Intent que descreve a solicitação do usuário junto com todos os dados de suporte. a Extensão de Aplicativo gera o objeto de Resposta apropriado para a Intenção especificada, detalhando como a extensão pode lidar com a solicitação.
Este guia apresentará um exemplo rápido de inclusão do suporte ao SiriKit em um aplicativo existente. Para este exemplo, usaremos o aplicativo falso MonkeyChat:
O MonkeyChat mantém sua própria lista de contatos dos amigos do usuário, cada um associado a um nome de tela (como Bobo, por exemplo), e permite que o usuário envie bate-papos de texto para cada amigo pelo nome de tela.
Estendendo o aplicativo com o SiriKit
Conforme mostrado no guia Noções básicas sobre os conceitos do SiriKit, há três partes principais envolvidas na extensão de um aplicativo com o SiriKit:
Estão incluídos:
- Extensão de intenções - Verifica as respostas dos usuários, confirma se o aplicativo pode lidar com a solicitação e realmente executa a tarefa para atender à solicitação do usuário.
- Extensão - de interface do usuário de intenções opcional, fornece uma interface do usuário personalizada para as respostas no ambiente da Siri e pode trazer a interface do usuário e a identidade visual dos aplicativos para a Siri para enriquecer a experiência do usuário.
- App - Fornece ao App vocabulários específicos do usuário para ajudar a Siri a trabalhar com ele.
Todos esses elementos e as etapas para incluí-los no aplicativo serão abordados em detalhes nas seções abaixo.
Preparando o aplicativo
O SiriKit é construído em extensões, no entanto, antes de adicionar qualquer extensão ao aplicativo, há algumas coisas que o desenvolvedor precisa fazer para ajudar na adoção do SiriKit.
Movendo código compartilhado comum
Primeiro, o desenvolvedor pode mover parte do código comum que será compartilhado entre o aplicativo e as extensões para Projetos Compartilhados, Bibliotecas de Classes Portáteis (PCLs) ou Bibliotecas Nativas.
As extensões precisarão ser capazes de fazer todas as coisas que o aplicativo faz. Nos termos do aplicativo MonkeyChat de amostra, coisas como encontrar contatos, adicionar novos contatos, enviar mensagens e recuperar o histórico de mensagens.
Ao mover esse código comum para um Projeto Compartilhado, PCL ou Biblioteca Nativa, facilita a manutenção desse código em um local comum e garante que a Extensão e o aplicativo pai forneçam experiências e funcionalidades uniformes para o usuário.
No caso do aplicativo de exemplo MonkeyChat, os modelos de dados e o código de processamento, como acesso à rede e ao banco de dados, serão movidos para uma biblioteca nativa.
Faça o seguinte:
Inicie o Visual Studio para Mac e abra o aplicativo MonkeyChat.
Clique com o botão direito do mouse no Nome da Solução no Painel de Soluções e selecione Adicionar>Novo Projeto...:
Selecione Biblioteca de Classes da Biblioteca>do iOS>e clique no botão Avançar:
Digite
MonkeyChatCommon
para o Nome e clique no botão Criar :Clique com o botão direito do mouse na pasta Referências do aplicativo principal no Gerenciador de Soluções e selecione Editar Referências.... Verifique o projeto MonkeyChatCommon e clique no botão OK:
No Gerenciador de Soluções, arraste o código compartilhado comum do aplicativo principal para a Biblioteca Nativa.
No caso do MonkeyChat, arraste as pastas DataModels e Processors do aplicativo principal para a Biblioteca Nativa:
Edite qualquer um dos arquivos que foram movidos para a Biblioteca Nativa e altere o namespace para corresponder ao da biblioteca. Por exemplo, mudar MonkeyChat
para MonkeyChatCommon
:
using System;
namespace MonkeyChatCommon
{
/// <summary>
/// A message sent from one user to another within a conversation.
/// </summary>
public class MonkeyMessage
{
public MonkeyMessage ()
{
}
...
}
}
Em seguida, volte para o aplicativo principal e adicione uma using
instrução para o namespace da Biblioteca Nativa em qualquer lugar em que o aplicativo use uma das classes que foram movidas:
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;
...
}
}
Arquitetando o aplicativo para extensões
Normalmente, um aplicativo se inscreve em várias intenções e o desenvolvedor precisa garantir que o aplicativo seja arquitetado para o número apropriado de extensões de intenção.
Na situação em que um aplicativo requer mais de uma Intenção, o desenvolvedor tem a opção de colocar todo o tratamento de Intenção em uma Extensão de Intenção ou criar uma Extensão de Intenção separada para cada Intenção.
Se optar por criar uma Extensão de Intenção separada para cada Intenção, o desenvolvedor poderá acabar duplicando uma grande quantidade de código clichê em cada extensão e criar uma grande quantidade de sobrecarga de processador e memória.
Para ajudar a escolher entre as duas opções, veja se alguma das intenções pertence naturalmente uma à outra. Por exemplo, um aplicativo que fez chamadas de áudio e vídeo pode querer incluir essas duas intenções em uma única extensão de intenção, pois eles estão lidando com tarefas semelhantes e podem fornecer a maior reutilização de código.
Para qualquer Intenção ou grupo de Intenções que não se encaixe em um grupo existente, crie uma nova Extensão de Intenção na solução do aplicativo para contê-las.
Definindo os direitos necessários
Qualquer aplicativo Xamarin.iOS que inclua a integração do SiriKit deve ter os direitos corretos definidos. Se o desenvolvedor não definir esses direitos necessários corretamente, ele não poderá instalar ou testar o aplicativo em hardware real do iOS 10 (ou superior), o que também é um requisito, pois o Simulador do iOS 10 não é compatível com o SiriKit.
Faça o seguinte:
Clique duas vezes no
Entitlements.plist
arquivo no Gerenciador de Soluções para abri-lo para edição.Alterne para a guia Origem.
Adicione a
com.apple.developer.siri
Propriedade, defina o Tipo comoBoolean
e o Valor comoYes
:Salve as alterações no arquivo.
Clique duas vezes no Arquivo de Projeto no Gerenciador de Soluções para abri-lo para edição.
Selecione Assinatura de Pacote do iOS e verifique se o
Entitlements.plist
arquivo está selecionado no campo Direitos Personalizados :Clique no botão OK para salvar as alterações.
Quando terminar, o arquivo do Entitlements.plist
aplicativo deve ser semelhante ao seguinte (aberto em um 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>
Provisionando corretamente o aplicativo
Devido à segurança estrita que a Apple colocou em torno da estrutura SiriKit, qualquer aplicativo Xamarin.iOS que implemente o SiriKit deve ter a ID do aplicativo e os direitos corretos (consulte a seção acima) e deve ser assinado com um perfil de provisionamento adequado.
Faça o seguinte no Mac:
Em um navegador da Web, navegue e https://developer.apple.com faça login em sua conta.
Clique em Certificados, Identificadores e Perfis.
Selecione Perfis de provisionamento, selecione IDs de aplicativo e clique no + botão.
Insira um Nome para o novo Perfil.
Insira um ID do pacote seguindo a recomendação de nomenclatura da Apple.
Role para baixo até a seção Serviços de Aplicativos, selecione SiriKit e clique no botão Continuar:
Verifique todas as configurações e envie a ID do aplicativo.
Selecione Desenvolvimento de Perfis>de Provisionamento, clique no + botão, selecione o ID Apple e clique em Continuar.
Clique em Selecionar tudo e, em seguida, clique em Continuar.
Clique em Selecionar tudo novamente e, em seguida, clique em Continuar.
Digite um Nome de Perfil usando as sugestões de nomenclatura da Apple e clique em Continuar.
Inicie o Xcode.
No menu Xcode, selecione Preferências...
Selecione Contas e clique no botão Exibir detalhes... :
Clique no botão Baixar todos os perfis no canto inferior esquerdo:
Verifique se o Perfil de Provisionamento criado acima foi instalado no Xcode.
Abra o projeto ao qual adicionar suporte ao SiriKit no Visual Studio para Mac.
Clique duas vezes no
Info.plist
arquivo no Gerenciador de Soluções.Verifique se o Identificador de Pacote corresponde ao criado no Portal do Desenvolvedor da Apple acima:
No Gerenciador de Soluções, selecione o Projeto.
Clique com o botão direito do mouse no projeto e selecione Opções.
Selecione Assinatura de Pacote do iOS, selecione a Identidade de Assinatura e o Perfil de Provisionamento criados acima:
Clique no botão OK para salvar as alterações.
Importante
Testar o SiriKit funciona apenas em um dispositivo de hardware iOS 10 real e não no simulador iOS 10. Se estiver tendo problemas para instalar um aplicativo Xamarin.iOS habilitado para SiriKit em hardware real, verifique se os Direitos, a ID do Aplicativo, o Identificador de Assinatura e o Perfil de Provisionamento necessários foram configurados corretamente no Portal do Desenvolvedor da Apple e no Visual Studio para Mac.
Solicitando autorização da Siri
Antes que o app adicione qualquer Vocabulário Específico do Usuário ou que as Extensões de Intenções se conectem à Siri, ele precisa solicitar autorização do usuário para acessar a Siri.
Edite o arquivo do Info.plist
aplicativo, alterne para a visualização Fonte e adicione a NSSiriUsageDescription
chave com um valor de string descrevendo como o aplicativo usará a Siri e quais tipos de dados serão enviados. Por exemplo, o aplicativo MonkeyChat pode dizer "Os contatos do MonkeyChat serão enviados para a Siri":
Chame o RequestSiriAuthorization
INPreferences
método da classe quando o aplicativo for iniciado pela primeira vez. Edite a AppDelegate.cs
classe e faça com que o FinishedLaunching
método se pareça com o seguinte:
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;
}
Na primeira vez que esse método é chamado, um alerta é exibido solicitando que o usuário permita que o aplicativo acesse a Siri. A mensagem que o desenvolvedor adicionou ao NSSiriUsageDescription
acima será exibida neste alerta. Se o usuário inicialmente negar o acesso, ele poderá usar o aplicativo Configurações para conceder acesso ao aplicativo.
A qualquer momento, o aplicativo pode verificar a capacidade do aplicativo de acessar a Siri chamando o SiriAuthorizationStatus
INPreferences
método da classe.
Localização e Siri
Em um dispositivo iOS, o usuário pode selecionar um idioma para a Siri diferente do padrão do sistema. Ao trabalhar com dados localizados, o aplicativo precisará usar o SiriLanguageCode
INPreferences
método da classe para obter o código de idioma da Siri. Por exemplo:
var language = INPreferences.SiriLanguageCode();
// Take action based on language
if (language == "en-US") {
// Do something...
}
Adicionando vocabulário específico do usuário
O Vocabulário Específico do Usuário fornecerá palavras ou frases exclusivas para usuários individuais do aplicativo. Eles serão fornecidos em tempo de execução do aplicativo principal (não das Extensões de Aplicativo) como um conjunto ordenado de termos, ordenados em uma prioridade de uso mais significativa para os usuários, com os termos mais importantes no início da lista.
O vocabulário específico do usuário deve pertencer a uma das seguintes categorias:
- Nomes de Contato (que não são gerenciados pela estrutura de Contatos).
- Tags de fotos.
- Nomes de álbuns de fotos.
- Nomes de exercícios.
Ao selecionar a terminologia para registrar como vocabulário personalizado, escolha apenas termos que possam ser mal interpretados por alguém não familiarizado com o aplicativo. Nunca registre termos comuns como "Meu treino" ou "Meu álbum". Por exemplo, o aplicativo MonkeyChat registrará os apelidos associados a cada contato no catálogo de endereços do usuário.
O aplicativo fornece o Vocabulário Específico do Usuário chamando o SetVocabularyStrings
INVocabulary
método da classe e passando uma NSOrderedSet
coleção do aplicativo principal. O aplicativo deve sempre chamar o RemoveAllVocabularyStrings
método primeiro, para remover todos os termos existentes antes de adicionar novos. Por exemplo:
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
}
}
Com esse código em vigor, ele pode ser chamado da seguinte maneira:
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
A Siri trata o vocabulário personalizado como dicas e incorporará o máximo possível da terminologia. No entanto, o espaço para vocabulário personalizado é limitado, tornando importante registrar apenas a terminologia que pode ser confusa, mantendo o número total de termos registrados no mínimo.
Para obter mais informações, consulte nossa Referência de vocabulário específico do usuário e a Referência de especificação de vocabulário personalizado da Apple.
Adicionando vocabulário específico do aplicativo
O Vocabulário Específico do Aplicativo define as palavras e frases específicas que serão conhecidas por todos os usuários do aplicativo, como tipos de veículos ou nomes de exercícios. Como eles fazem parte do aplicativo, eles são definidos em um AppIntentVocabulary.plist
arquivo como parte do pacote de aplicativos principal. Além disso, essas palavras e frases devem ser localizadas.
Os termos do Vocabulário Específico do Aplicativo devem pertencer a uma das seguintes categorias:
- Opções de passeio.
- Nomes de exercícios.
O arquivo de vocabulário específico do aplicativo contém duas chaves de nível raiz:
ParameterVocabularies
Obrigatório - Define os termos personalizados do aplicativo e os parâmetros de intenção aos quais eles se aplicam.IntentPhrases
Opcional - Contém frases de exemplo usando os termos personalizados definidos noParameterVocabularies
.
Cada entrada no ParameterVocabularies
deve especificar uma string de ID, um termo e a intenção à qual o termo se aplica. Além disso, um único termo pode se aplicar a várias intenções.
Para obter uma lista completa de valores aceitáveis e estrutura de arquivos necessária, consulte a Referência de formato de arquivo de vocabulário de aplicativos da Apple.
Para adicionar um AppIntentVocabulary.plist
arquivo ao projeto do aplicativo, faça o seguinte:
Clique com o botão direito do mouse no Nome do Projeto no Gerenciador de Soluções e selecione Adicionar>Novo Arquivo...>iOS:
Clique duas vezes no
AppIntentVocabulary.plist
arquivo no Gerenciador de Soluções para abri-lo para edição.Clique em + para adicionar uma chave, defina o Nome como
ParameterVocabularies
e o Tipo comoArray
:Expanda
ParameterVocabularies
e clique no + botão e defina o Tipo comoDictionary
:Clique em + para adicionar uma nova chave, defina o Nome como
ParameterNames
e o Tipo comoArray
:Clique em para + adicionar uma nova chave com o Tipo de
String
e o valor como um dos Nomes de parâmetro disponíveis. Por exemploINStartWorkoutIntent.workoutName
:Adicione a
ParameterVocabulary
chave àParameterVocabularies
chave com o tipo deArray
:Adicione uma nova chave com o tipo de
Dictionary
:Adicione a
VocabularyItemIdentifier
chave com o Type deString
e especifique um ID exclusivo para o termo:Adicione a
VocabularyItemSynonyms
chave com o Tipo deArray
:Adicione uma nova chave com o tipo de
Dictionary
:Adicione a
VocabularyItemPhrase
chave com o Tipo deString
e o termo que o aplicativo está definindo:Adicione a
VocabularyItemPronunciation
chave com o Tipo deString
e a pronúncia fonética do termo:Adicione a
VocabularyItemExamples
chave com o Tipo deArray
:Adicione algumas
String
chaves com exemplos de usos do termo:Repita as etapas acima para quaisquer outros termos personalizados que o aplicativo precise definir.
Recolha a
ParameterVocabularies
chave.Adicione a
IntentPhrases
chave com o Tipo deArray
:Adicione uma nova chave com o tipo de
Dictionary
:Adicione a
IntentName
chave com o Tipo deString
e a Intenção para o exemplo:Adicione a
IntentExamples
chave com o Tipo deArray
:Adicione algumas
String
chaves com exemplos de usos do termo:Repita as etapas acima para todas as intenções das quais o aplicativo precisa fornecer um exemplo de uso.
Importante
Eles AppIntentVocabulary.plist
serão registrados com a Siri nos dispositivos de teste durante o desenvolvimento e pode levar algum tempo para que a Siri incorpore o vocabulário personalizado. Como resultado, o testador precisará aguardar vários minutos antes de tentar testar o Vocabulário Específico do Aplicativo quando ele for atualizado.
Para obter mais informações, consulte nossa Referência de vocabulário específico do aplicativo e Referência de vocabulário personalizado Especificando da Apple.
Adicionando uma extensão de intenções
Agora que o aplicativo foi preparado para adotar o SiriKit, o desenvolvedor precisará adicionar uma (ou mais) Extensões de Intenções à solução para lidar com as Intenções necessárias para a integração da Siri.
Para cada Extensão de Intenções necessária, faça o seguinte:
- Adicione um projeto de Extensão de Intenções à solução de aplicativo Xamarin.iOS.
- Configure o arquivo de extensão
Info.plist
de intenções. - Modifique a classe principal da Extensão de Intenções.
Para obter mais informações, consulte nossa Referência de extensão de intenções e a referência Criando a extensão de intenções da Apple.
Criando a extensão
Para adicionar uma Extensão de Intenções à solução, faça o seguinte:
Clique com o botão direito do mouse no Nome da Solução no Painel de Soluções e selecione Adicionar>Adicionar Novo Projeto....
Na caixa de diálogo, selecione Extensão de intenção de extensões>do iOS>e clique no botão Avançar:
Em seguida, insira um Nome para a Extensão de Intenção e clique no botão Avançar :
Por fim, clique no botão Criar para adicionar a Extensão de Intenção à solução de aplicativos:
No Gerenciador de Soluções, clique com o botão direito do mouse na pasta Referências da Extensão de Intenção recém-criada. Verifique o nome do projeto de biblioteca de código compartilhado comum (que o aplicativo criou acima) e clique no botão OK :
Repita essas etapas para o número de Extensões de Intenção (com base na seção Arquitetando o Aplicativo para Extensões acima) que o aplicativo exigirá.
Configurando o Info.plist
Para cada uma das Extensões de Intenções que foram adicionadas à solução do aplicativo, devem ser configuradas Info.plist
nos arquivos para funcionar com o aplicativo.
Assim como qualquer Extensão de Aplicativo típica, o aplicativo terá as chaves existentes de NSExtension
e NSExtensionAttributes
. Para uma Extensão de Intenções, há dois novos atributos que devem ser configurados:
- IntentsSupported – é necessário e consiste em uma matriz de nomes de classe de intenção que o aplicativo deseja dar suporte à partir da extensão de intenção.
- IntentsRestrictedWhileLocked - É uma chave opcional para o aplicativo especificar o comportamento da tela de bloqueio da extensão. Ele consiste em uma matriz de nomes de classe de intenção que o aplicativo deseja exigir que o usuário esteja conectado para usar a partir da extensão de intenção.
Para configurar o arquivo da Info.plist
Extensão de Intenção, clique duas vezes nele no Gerenciador de Soluções para abri-lo para edição. Em seguida, alterne para a visualização Fonte e expanda as NSExtension
teclas e NSExtensionAttributes
no editor:
Expanda a IntentsSupported
chave e adicione o nome de qualquer classe de intenção à qual essa extensão dará suporte. Para o aplicativo MonkeyChat de exemplo, ele suporta o INSendMessageIntent
:
Se o aplicativo exigir opcionalmente que o usuário esteja conectado ao dispositivo para usar uma determinada intenção, expanda a IntentRestrictedWhileLocked
chave e adicione os nomes de classe das intenções que têm acesso restrito. Para o aplicativo MonkeyChat de exemplo, o usuário deve estar logado para enviar uma mensagem de bate-papo, portanto, adicionamos INSendMessageIntent
:
Para obter uma lista completa dos domínios de intenção disponíveis, consulte a Referência de domínios de intenção da Apple.
Configurando a classe principal
Em seguida, o desenvolvedor precisará configurar a classe principal que atua como o ponto de entrada principal para a Extensão de Intenção na Siri. Deve ser uma subclasse que INExtension
esteja em conformidade com o IINIntentHandler
delegado. Por exemplo:
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
...
}
}
Há um método solitário que o aplicativo deve implementar na classe principal da Extensão de Intenção, o GetHandler
método. Esse método recebe um Intent do SiriKit e o aplicativo deve retornar um Intent Handler que corresponda ao tipo do Intent fornecido.
Como o aplicativo MonkeyChat de exemplo lida apenas com uma intenção, ele está retornando a GetHandler
si mesmo no método. Se a extensão manipulasse mais de uma intenção, o desenvolvedor adicionaria uma classe para cada tipo de intenção e retornaria uma instância aqui com base no Intent
método passado.
Manipulando o estágio de resolução
O Estágio de Resolução é onde a Extensão de Intenção esclarecerá e validará os parâmetros passados pela Siri e foram definidos por meio da conversa do usuário.
Para cada parâmetro enviado da Siri, há um Resolve
método. O aplicativo precisará implementar esse método para cada parâmetro que o aplicativo possa precisar da ajuda da Siri para obter a resposta correta do usuário.
No caso do aplicativo MonkeyChat de exemplo, a Extensão de Intenção exigirá um ou mais destinatários para enviar a mensagem. Para cada destinatário na lista, a extensão precisará fazer uma pesquisa de contato que pode ter o seguinte resultado:
- Exatamente um contato correspondente é encontrado.
- Dois ou mais contatos correspondentes são encontrados.
- Nenhum contato correspondente foi encontrado.
Além disso, o MonkeyChat requer conteúdo para o corpo da mensagem. Se o usuário não tiver fornecido isso, a Siri precisará solicitar o conteúdo ao usuário.
A Extensão de Intenção precisará lidar normalmente com cada um desses 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 obter mais informações, consulte nossa Referência do estágio de resolução e a Referência de intenções de resolução e tratamento da Apple.
Manipulando o estágio de confirmação
O Estágio de Confirmação é onde a Extensão de Intenção verifica se tem todas as informações para atender à solicitação do usuário. O aplicativo deseja enviar confirmação junto com todos os detalhes de suporte do que está prestes a acontecer com a Siri para que possa ser confirmado com o usuário que esta é a ação pretendida.
[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 obter mais informações, consulte nossa Referência do estágio de confirmação.
Processando a intenção
Este é o ponto em que a Extensão de Intenção realmente executa a tarefa para atender à solicitação do usuário e passar os resultados de volta para a Siri para que o usuário possa 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 obter mais informações, consulte nossa Referência do estágio de alça.
Adicionando uma extensão de interface do usuário de intenções
A extensão de interface do usuário opcional Intents apresenta a oportunidade de trazer a interface do usuário e a identidade visual do aplicativo para a experiência da Siri e fazer com que os usuários se sintam conectados ao aplicativo. Com esta extensão, o aplicativo pode trazer a marca, bem como informações visuais e outras informações para a transcrição.
Assim como a Extensão de Intenções, o desenvolvedor executará a seguinte etapa para a Extensão de Interface do Usuário de Intenções:
- Adicione um projeto de Extensão de Interface do Usuário de Intenções à solução de aplicativo Xamarin.iOS.
- Configure o arquivo de extensão
Info.plist
de interface do usuário de intenções. - Modifique a classe principal da Extensão da Interface do Usuário de Intenções.
Para obter mais informações, consulte nossa Referência de extensão de interface do usuário The Intents e Referência de fornecimento de uma interface personalizada da Apple.
Criando a extensão
Para adicionar uma Extensão de Interface do Usuário de Intenções à solução, faça o seguinte:
Clique com o botão direito do mouse no Nome da Solução no Painel de Soluções e selecione Adicionar>Adicionar Novo Projeto....
Na caixa de diálogo, selecione Extensões> de interface do usuário de intenção de extensões do iOS>e clique no botão Avançar:
Em seguida, insira um Nome para a Extensão de Intenção e clique no botão Avançar :
Por fim, clique no botão Criar para adicionar a Extensão de Intenção à solução de aplicativos:
No Gerenciador de Soluções, clique com o botão direito do mouse na pasta Referências da Extensão de Intenção recém-criada. Verifique o nome do projeto de biblioteca de código compartilhado comum (que o aplicativo criou acima) e clique no botão OK :
Configurando o Info.plist
Configure o arquivo da Extensão de Interface do Usuário de Info.plist
Intenções para funcionar com o aplicativo.
Assim como qualquer Extensão de Aplicativo típica, o aplicativo terá as chaves existentes de NSExtension
e NSExtensionAttributes
. Para uma Extensão de Intenções, há um novo atributo que deve ser configurado:
IntentsSupported é necessário e consiste em uma matriz de nomes de classe de intenção que o aplicativo deseja dar suporte a partir da extensão de intenção.
Para configurar o arquivo da Extensão de Interface do Usuário de Info.plist
Intenção, clique duas vezes nele no Gerenciador de Soluções para abri-lo para edição. Em seguida, alterne para a visualização Fonte e expanda as NSExtension
teclas e NSExtensionAttributes
no editor:
Expanda a IntentsSupported
chave e adicione o nome de qualquer classe de intenção à qual essa extensão dará suporte. Para o aplicativo MonkeyChat de exemplo, ele suporta o INSendMessageIntent
:
Para obter uma lista completa dos domínios de intenção disponíveis, consulte a Referência de domínios de intenção da Apple.
Configurando a classe principal
Configure a classe principal que atua como o ponto de entrada principal para a Extensão de Interface do Usuário de Intenção na Siri. Deve ser uma subclasse que UIViewController
esteja em conformidade com a IINUIHostedViewController
interface. Por exemplo:
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
}
}
A Siri passará uma INInteraction
instância de classe para o Configure
método da UIViewController
instância dentro da Extensão de Interface do Usuário de Intenção.
O INInteraction
objeto fornece três informações principais para a extensão:
- O objeto Intent que está sendo processado.
- O objeto Resposta de Intenção dos
Confirm
métodos eHandle
da Extensão de Intenção. - O Estado de Interação que define o estado da interação entre o aplicativo e a Siri.
A UIViewController
instância é a classe principal para a interação com a Siri e, como herda de UIViewController
, tem acesso a todos os recursos do UIKit.
Quando a Siri chama o Configure
método, UIViewController
ele passa em um contexto de exibição informando que o controlador de exibição será hospedado em um snippit da Siri ou em um cartão de mapas.
A Siri também passará um manipulador de conclusão que o aplicativo precisa retornar o tamanho desejado da exibição depois que o aplicativo terminar de configurá-lo.
Projetar a interface do usuário no iOS Designer
Faça o layout da interface do usuário da Extensão de Interface do Usuário de Intenções no Designer do iOS. Clique duas vezes no arquivo da MainInterface.storyboard
extensão no Gerenciador de Soluções para abri-lo para edição. Arraste todos os elementos de interface do usuário necessários para criar a interface do usuário e salvar as alterações.
Importante
Embora seja possível adicionar elementos interativos, como UIButtons
ou UITextFields
para a extensão da interface do usuário de intenção, eles são estritamente proibidos UIViewController
, pois a interface do usuário de intenção não é interativa e o usuário não poderá interagir com eles.
Conecte a interface do usuário
Com a interface do usuário da extensão de interface do usuário de intenções criada no Designer do iOS, edite a UIViewController
subclasse e substitua o Configure
método da seguinte maneira:
[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 ();
}
Substituindo a interface padrão da Siri
A extensão de interface do usuário de intenções sempre será exibida junto com outros conteúdos da Siri, como o ícone e o nome do aplicativo na parte superior da interface do usuário ou, com base na intenção, botões (como Enviar ou Cancelar) podem ser exibidos na parte inferior.
Existem alguns casos em que o aplicativo pode substituir as informações que a Siri está exibindo para o usuário por padrão, como mensagens ou mapas em que o aplicativo pode substituir a experiência padrão por uma personalizada para o aplicativo.
Se a Extensão de Interface do Usuário de Intenções precisar substituir elementos da interface do usuário padrão da Siri, a UIViewController
subclasse precisará implementar a IINUIHostedViewSiriProviding
interface e optar por exibir um elemento de interface específico.
Adicione o seguinte código à UIViewController
subclasse para informar à Siri que a Extensão de Interface do Usuário de Intenção já está exibindo o conteúdo da mensagem:
public bool DisplaysMessage {
get {return true;}
}
Considerações
A Apple sugere que o desenvolvedor leve em consideração as seguintes considerações ao projetar e implementar as Extensões de Interface do Usuário de Intenção:
- Esteja ciente do uso de memória – como as extensões de interface do usuário de intenção são temporárias e mostradas apenas por um curto período de tempo, o sistema impõe restrições de memória mais rígidas do que as usadas com um aplicativo completo.
- Considere os tamanhos de exibição mínimo e máximo – verifique se as extensões de interface do usuário de intenção têm uma boa aparência em todos os tipos, tamanhos e orientações de dispositivos iOS. Além disso, o tamanho desejado que o aplicativo envia de volta para a Siri pode não ser concedido.
- Use padrões de layout flexíveis e adaptáveis – novamente, para garantir que a interface do usuário tenha uma ótima aparência em todos os dispositivos.
Resumo
Este artigo abordou o SiriKit e mostrou como ele pode ser adicionado aos aplicativos Xamarin.iOS para fornecer serviços acessíveis ao usuário usando a Siri e o aplicativo Mapas em um dispositivo iOS.