Поделиться через


Реализация SiriKit в Xamarin.iOS

В этой статье рассматриваются действия, необходимые для реализации поддержки SiriKit в приложениях Xamarin.iOS.

Новое в iOS 10, SiriKit позволяет приложению Xamarin.iOS предоставлять службы, доступные пользователю с помощью Siri и приложения Карты на устройстве iOS. В этой статье рассматриваются действия, необходимые для реализации поддержки SiriKit в приложениях Xamarin.iOS, добавив необходимые расширения намерений, расширения пользовательского интерфейса намерений и словарь.

Siri работает с понятием "Домены", группами известных действий для связанных задач. Каждое взаимодействие, которое приложение имеет с Siri, должно попасть в один из известных доменов службы следующим образом:

  • Звук или видеозвонок.
  • Бронирование поездки.
  • Управление тренировками.
  • (Проекты разработки с открытым кодом в .NET).
  • Поиск фотографий.
  • Отправка или получение платежей.

Когда пользователь отправляет запрос Siri с участием одной из служб расширения приложения, SiriKit отправляет расширение объект Intent , описывающий запрос пользователя вместе с любыми вспомогательными данными. Затем расширение приложения создает соответствующий объект Response для заданного намерения, подробные сведения о том, как расширение может обрабатывать запрос.

В этом руководстве представлен краткий пример включения поддержки SiriKit в существующее приложение. Для этого примера мы будем использовать поддельные приложение MonkeyChat:

Значок MonkeyChat

MonkeyChat хранит свою собственную контактную книгу друзей пользователя, каждая из которых связана с именем экрана (например, Bobo), и позволяет пользователю отправлять текстовые чаты каждому другу по имени экрана.

Расширение приложения с помощью SiriKit

Как показано в руководстве по концепциям SiriKit, существует три основных компонента, участвующих в расширении приложения с помощью SiriKit:

Расширение приложения с помощью схемы SiriKit

Например:

  1. Расширение "Намерения" — проверяет ответы пользователей, подтверждает, что приложение может обрабатывать запрос и фактически выполняет задачу для выполнения запроса пользователя.
  2. Необязательное расширение - пользовательского интерфейса намерений предоставляет пользовательский интерфейс для ответов в среде Siri и может перенести пользовательский интерфейс приложений и фирменную символику в Siri, чтобы обогатить взаимодействие с пользователем.
  3. Приложение — предоставляет приложению специальные словари, помогая Siri работать с ним.

Все эти элементы и действия по их включению в приложение будут подробно описаны в разделах ниже.

Подготовка приложения

SiriKit основан на расширениях, однако перед добавлением расширений в приложение есть несколько вещей, которые разработчик должен сделать, чтобы помочь в внедрении SiriKit.

Перемещение общего кода

Во-первых, разработчик может переместить некоторый общий код, который будет использоваться между приложением и расширениями в общие проекты, переносимые библиотеки классов (PCLs) или собственные библиотеки.

Расширения должны иметь возможность выполнять все действия, которые делает приложение. С точки зрения примера приложения MonkeyChat, такие как поиск контактов, добавление новых контактов, отправка сообщений и получение журнала сообщений.

Переместив этот общий код в общий проект, PCL или собственную библиотеку, он упрощает обслуживание этого кода в одном общем месте и гарантирует, что расширение и родительское приложение предоставляют универсальные возможности и функциональные возможности для пользователя.

В случае примера приложения MonkeyChat модели данных и код обработки, такие как доступ к сети и базе данных, будут перемещены в собственную библиотеку.

Выполните следующие действия.

  1. Запустите Visual Studio для Mac и откройте приложение MonkeyChat.

  2. Щелкните правой кнопкой мыши имя решения на панели решения и выберите "Добавить>новый проект"...:

    Добавление нового проекта

  3. Выберите библиотеку классов библиотеки библиотеки>iOS>и нажмите кнопку "Далее":

    Выберите элемент Библиотека классов.

  4. Введите MonkeyChatCommon имя и нажмите кнопку "Создать":

    Введите MonkeyChatCommon для имени

  5. Щелкните правой кнопкой мыши папку "Ссылки" основного приложения в Обозреватель решений и выберите "Изменить ссылки...". Проверьте проект MonkeyChatCommon и нажмите кнопку ОК:

    Проверка проекта MonkeyChatCommon

  6. В Обозреватель решений перетащите общий код из основного приложения в собственную библиотеку.

  7. В случае MonkeyChat перетащите папки DataModels и Процессоры из основного приложения в собственную библиотеку:

    Папки DataModels и Процессоры в Обозреватель решений

Измените любой из файлов, которые были перемещены в собственную библиотеку, и измените пространство имен на соответствие библиотеке. Например, изменение MonkeyChat на MonkeyChatCommon:

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

Затем вернитесь к основному приложению и добавьте using инструкцию для пространства имен собственной библиотеки в любом месте, где приложение использует один из классов, которые были перемещены:

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;
        ...
    }
}

Проектирование приложения для расширений

Как правило, приложение регистрируется для нескольких намерений, и разработчик должен убедиться, что приложение разработано для соответствующего количества расширений намерений.

В ситуации, когда приложению требуется несколько намерений, разработчик может разместить все его действия в одном расширении намерения или создать отдельное расширение намерения для каждого намерения.

Если вы хотите создать отдельное расширение намерения для каждого намерения, разработчик может в конечном итоге дублировать большой объем стандартного кода в каждом расширении и создать большое количество ресурсов процессора и памяти.

Чтобы выбрать один из двух вариантов, ознакомьтесь с тем, принадлежат ли какие-либо намерения вместе. Например, приложение, выполняющее аудио- и видеозвонки, может потребоваться включить оба этих намерения в одно расширение намерения, так как они обрабатывают аналогичные задачи и могут обеспечить максимальное использование кода.

Для любого намерения или группы намерений, которые не вписываются в существующую группу, создайте новое расширение намерения в решении приложения для их хранения.

Настройка обязательных прав

Любое приложение Xamarin.iOS, включающее интеграцию SiriKit, должно иметь правильные права. Если разработчик не правильно устанавливает эти необходимые права, они не смогут устанавливать или тестировать приложение на реальном оборудовании iOS 10 (или более поздней версии), что также требуется, так как симулятор iOS 10 не поддерживает SiriKit.

Выполните следующие действия.

  1. Дважды щелкните Entitlements.plist файл в Обозреватель решений, чтобы открыть его для редактирования.

  2. Перейдите на вкладку Источник.

  3. com.apple.developer.siriДобавьте свойство, задайте Boolean тип и значениеYes:

    Добавление свойства com.apple.developer.siri

  4. Сохраните изменения в файле.

  5. Дважды щелкните файл проекта в Обозреватель решений, чтобы открыть его для редактирования.

  6. Выберите подпись пакета iOS и убедитесь, что Entitlements.plist файл выбран в поле "Пользовательские права" :

    Выберите файл Entitlements.plist в поле

  7. Нажмите кнопку ОК, чтобы сохранить изменения.

По завершении файл приложения Entitlements.plist должен выглядеть следующим образом (в открытом в внешнем редакторе):

<?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>

Правильная подготовка приложения

Из-за строгой безопасности, размещенной Apple на платформе SiriKit, любое приложение Xamarin.iOS, реализующее SiriKit , должно иметь правильный идентификатор приложения и права (см. раздел выше) и подписывается соответствующим профилем подготовки.

Выполните следующие действия на компьютере Mac:

  1. В веб-браузере перейдите к https://developer.apple.com учетной записи и войдите в нее.

  2. Щелкните сертификаты, идентификаторы и профили.

  3. Выберите профили подготовки и выберите идентификаторы приложений, а затем нажмите кнопку + .

  4. Введите имя нового профиля.

  5. Введите идентификатор пакета после рекомендации по именованию Apple.

  6. Прокрутите вниз до раздела Служба приложений, выберите SiriKit и нажмите кнопку "Продолжить".

    Выбор SiriKit

  7. Проверьте все параметры, а затем отправьте идентификатор приложения.

  8. Выберите "Разработка профилей>подготовки", нажмите + кнопку, выберите Идентификатор Apple ID, а затем нажмите кнопку "Продолжить".

  9. Нажмите кнопку "Выбрать все", а затем нажмите кнопку "Продолжить".

  10. Нажмите кнопку " Выбрать все снова", а затем нажмите кнопку "Продолжить".

  11. Введите имя профиля с помощью предложений по именованию Apple, а затем нажмите кнопку "Продолжить".

  12. Запустите Xcode.

  13. В меню Xcode выберите параметры...

  14. Выберите "Учетные записи", а затем нажмите кнопку "Просмотреть сведения...

    Выбор элемента

  15. Нажмите кнопку "Скачать все профили" в левом нижнем углу:

    Скачивание всех профилей

  16. Убедитесь, что созданный выше профиль подготовки установлен в Xcode.

  17. Откройте проект, чтобы добавить поддержку SiriKit в Visual Studio для Mac.

  18. Дважды щелкните Info.plist файл в Обозреватель решений.

  19. Убедитесь, что идентификатор пакета соответствует идентификатору пакета, созданному на портале разработчика Apple, приведенному выше:

    Идентификатор пакета

  20. В Обозреватель решений выберите проект.

  21. Щелкните проект правой кнопкой мыши и выберите пункт "Параметры".

  22. Выберите подписывание пакета iOS, выберите удостоверение подписи и профиль подготовки, созданный выше:

    Выберите удостоверение подписи и профиль подготовки

  23. Нажмите кнопку ОК, чтобы сохранить изменения.

Внимание

Тестирование SiriKit работает только на реальном аппаратном устройстве iOS 10, а не в симуляторе iOS 10. Если возникли проблемы с установкой приложения Xamarin.iOS с поддержкой SiriKit на реальном оборудовании, убедитесь, что необходимые права, идентификатор приложения, идентификатор подписи и профиль подготовки настроены на портале разработчика Apple и Visual Studio для Mac.

Запрос авторизации Siri

Прежде чем приложение добавляет любой словарь пользователя или расширения намерений подключается к Siri, он должен запрашивать авторизацию от пользователя для доступа к Siri.

Измените файл приложения Info.plist , перейдите в представление источника и добавьте NSSiriUsageDescription ключ со строковым значением, описывающим, как приложение будет использовать Siri и какие типы данных будут отправляться. Например, приложение MonkeyChat может сказать: "Контакты MonkeyChat будут отправлены в Siri":

NSSiriUsageDescription в редакторе Info.plist

RequestSiriAuthorization Вызовите метод INPreferences класса при первом запуске приложения. Измените AppDelegate.cs класс и сделайте FinishedLaunching метод следующим образом:

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;
}

При первом вызове этого метода отображается оповещение, предлагающее пользователю разрешить приложению доступ к Siri. В этом оповещении будет отображаться сообщение, которое разработчик добавил в приведенное NSSiriUsageDescription выше оповещение. Если пользователь изначально запрещает доступ, он может использовать приложение Параметры для предоставления доступа к приложению.

В любое время приложение может проверка возможности приложения получить доступ к Siri, вызвав SiriAuthorizationStatus метод INPreferences класса.

Локализация и Siri

На устройстве iOS пользователь может выбрать язык для Siri, который отличается от системного по умолчанию. При работе с локализованными данными приложению потребуется использовать SiriLanguageCode метод INPreferences класса для получения языкового кода из Siri. Например:

var language = INPreferences.SiriLanguageCode();

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

Добавление словаря для конкретного пользователя

Словарь конкретного пользователя будет предоставлять слова или фразы, уникальные для отдельных пользователей приложения. Они будут предоставлены во время выполнения из основного приложения (а не расширения приложений) в качестве упорядоченного набора терминов, упорядоченных в наиболее важном приоритете использования для пользователей, с наиболее важными терминами в начале списка.

Словарь конкретного пользователя должен принадлежать к одной из следующих категорий:

  • Имена контактов (которые не управляются платформой контактов).
  • Теги фотографий.
  • Имена фотоальбомов.
  • Имена тренировки.

При выборе терминологии для регистрации в качестве пользовательского словаря выберите только термины, которые могут быть неправильно поняты кем-то, кто не знаком с приложением. Никогда не регистрируйте распространенные термины, такие как "My Workout" или "Мой альбом". Например, приложение MonkeyChat регистрирует псевдонимы, связанные с каждым контактом в адресной книге пользователя.

Приложение предоставляет словарь для конкретного INVocabulary пользователя, вызывая SetVocabularyStrings метод класса и передав NSOrderedSet коллекцию из основного приложения. Приложение всегда должно вызывать RemoveAllVocabularyStrings метод первым, чтобы удалить все существующие термины перед добавлением новых. Например:

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
    }
}

На месте этот код может вызываться следующим образом:

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
    }
}

Внимание

Siri обрабатывает пользовательский словарь как подсказки и будет включать как можно больше терминологии. Однако пространство для пользовательского словаря ограничивается тем, что важно зарегистрировать только терминологию, которая может быть запутана, поэтому общее число зарегистрированных терминов должно быть минимальным.

Дополнительные сведения см. в справочнике по словарю для конкретного пользователя и указании пользовательского словаря Apple.

Добавление определенного словаря приложения

Словарь конкретного приложения определяет конкретные слова и фразы, которые будут известны всем пользователям приложения, например типам транспортных средств или именам тренировки. Так как они являются частью приложения, они определяются в файле в AppIntentVocabulary.plist составе основного пакета приложений. Кроме того, эти слова и фразы должны быть локализованы.

Термины определенного словаря приложений должны принадлежать к одной из следующих категорий:

  • Параметры езды.
  • Имена тренировки.

Файл словаря для конкретного приложения содержит два ключа корневого уровня:

  • ParameterVocabulariesОбязательный. Определяет пользовательские термины приложения и параметры намерения, к которые они применяются.
  • IntentPhrasesНеобязательно . Содержит примеры фраз с помощью пользовательских терминов, определенных в параметре ParameterVocabularies.

Каждая запись в поле ParameterVocabularies должна указывать строку идентификатора, термин и намерение, к которому применяется термин. Кроме того, один термин может применяться к нескольким намерениям.

Полный список допустимых значений и требуемой структуры файлов см. в справочнике по формату файлов в словаре приложений Apple.

Чтобы добавить AppIntentVocabulary.plist файл в проект приложения, сделайте следующее:

  1. Щелкните правой кнопкой мыши имя проекта в Обозреватель решений и выберите "Добавить>новый файл".>iOS:

    Добавление списка свойств

  2. Дважды щелкните AppIntentVocabulary.plist файл в Обозреватель решений, чтобы открыть его для редактирования.

  3. + Щелкните клавишу, чтобы добавить ключ, задайте имяParameterVocabularies и типArray:

    Задайте для параметра ParameterVocabularies имя и тип массива

  4. Разверните ParameterVocabularies и нажмите + кнопку и задайте для типаDictionary:

    Задайте для типа словарь

  5. + Щелкните, чтобы добавить новый ключ, задайте имяParameterNames и типArray:

    Задайте для параметра имя и тип массива

  6. + Щелкните, чтобы добавить новый ключ с типомString и значением в качестве одного из доступных имен параметров. Например, INStartWorkoutIntent.workoutName:

    Ключ INStartWorkoutIntent.workoutName

  7. Добавьте ключ в ParameterVocabulary ключ с типом Array:ParameterVocabularies

    Добавьте ключ ParameterVocabulary в ключ ParameterVocabularies с типом массива

  8. Добавьте новый ключ с типом Dictionary:

    Добавьте новый ключ с типом словаря в Visual Studio для Mac.

  9. VocabularyItemIdentifier Добавьте ключ с типомString и укажите уникальный идентификатор для термина:

    Добавьте ключ СловаряItemIdentifier с типом строки и укажите уникальный идентификатор.

  10. VocabularyItemSynonyms Добавьте ключ с типомArray:

    Добавление ключа СловаряItemSynonyms с типом массива

  11. Добавьте новый ключ с типом Dictionary:

    Добавьте еще один новый ключ с типом словаря в Visual Studio для Mac.

  12. VocabularyItemPhrase Добавьте ключ с типомString и термином, определяющим приложение:

    Добавьте ключ СловаряItemPhrase с типом строки и термином, определяющим приложение

  13. VocabularyItemPronunciation Добавьте ключ с типомString и фонетическим произношением термина:

    Добавьте ключ СловаряItemPronunciation с типом строки и фонетичным произношением термина

  14. VocabularyItemExamples Добавьте ключ с типомArray:

    Добавление ключа СловаряItemExamples с типом массива

  15. Добавьте несколько String ключей с примером использования термина:

    Добавьте несколько строковых ключей с примером использования термина в Visual Studio для Mac.

  16. Повторите описанные выше действия для любых других пользовательских терминов, которые необходимо определить приложению.

  17. ParameterVocabularies Свернуть ключ.

  18. IntentPhrases Добавьте ключ с типомArray:

    Добавление ключа IntentPhrases с типом массива

  19. Добавьте новый ключ с типом Dictionary:

    Добавьте дополнительный ключ с типом словаря в Visual Studio для Mac.

  20. IntentName Добавьте ключ с типомString и намерением для примера:

    Добавьте ключ IntentName с типом строки и намерения в примере

  21. IntentExamples Добавьте ключ с типомArray:

    Добавление ключа IntentExamples с типом массива

  22. Добавьте несколько String ключей с примером использования термина:

    Добавьте несколько дополнительных ключей string с примером использования термина в Visual Studio для Mac.

  23. Повторите описанные выше действия для любых намерений, которые приложение необходимо предоставить пример использования.

Внимание

Оно AppIntentVocabulary.plist будет зарегистрировано в Siri на тестовых устройствах во время разработки и может занять некоторое время, чтобы Siri включала пользовательский словарь. В результате тестировщику потребуется подождать несколько минут, прежде чем пытаться протестировать словарь для конкретного приложения при обновлении.

Дополнительные сведения см. в справочнике по словарю для конкретного приложения и справочнике по пользовательскому словарю Apple.

Добавление расширения намерений

Теперь, когда приложение готово к внедрению SiriKit, разработчику потребуется добавить в решение одно (или несколько) расширений намерений для обработки намерений, необходимых для интеграции Siri.

Для каждого расширения намерений выполните следующие действия.

  • Добавьте проект расширения "Намерения" в решение приложения Xamarin.iOS.
  • Настройте файл расширения намерений Info.plist .
  • Измените основной класс Расширения Намерений.

Дополнительные сведения см. в справочнике по расширению "Намерения" и справочнике по созданию расширения "Намерения" Apple.

Создание расширения

Чтобы добавить расширение "Намерения" в решение, сделайте следующее:

  1. Щелкните правой кнопкой мыши имя решения на панели решения и выберите добавить>новый проект....

  2. В диалоговом окне выберите расширение намерения расширений>iOS>и нажмите кнопку "Далее".

    Выбор расширения намерения

  3. Затем введите имя расширения намерения и нажмите кнопку "Далее ":

    Введите имя расширения намерения.

  4. Наконец, нажмите кнопку "Создать ", чтобы добавить расширение намерения в решение приложений:

    Добавьте расширение намерения в решение приложений.

  5. В Обозреватель решений щелкните правой кнопкой мыши папку "Ссылки" только что созданного расширения намерения. Проверьте имя проекта общей библиотеки кода (созданного выше приложения) и нажмите кнопку ОК :

    Выберите имя общего проекта библиотеки кода.

Повторите эти действия для количества расширений намерений (на основе архитектуры приложения для расширений выше), необходимых приложению.

Настройка info.plist

Для каждого расширения намерений, добавленных в решение приложения, необходимо настроить в Info.plist файлах для работы с приложением.

Как и любое типичное расширение приложения, приложение будет иметь существующие ключи NSExtension и NSExtensionAttributes. Для расширения намерений есть два новых атрибута, которые необходимо настроить:

Два новых атрибута, которые необходимо настроить

  • IntentsSupported — требуется и состоит из массива имен классов намерений, которые приложение хочет поддерживать из расширения намерения.
  • IntentsRestrictedTimeLocked — это необязательный ключ для приложения, чтобы указать поведение экрана блокировки расширения. Он состоит из массива имен классов намерений, которые приложение хочет требовать, чтобы пользователь вошел в систему из расширения намерения.

Чтобы настроить файл расширения Info.plist намерения, дважды щелкните его в Обозреватель решений, чтобы открыть его для редактирования. Затем перейдите к представлению источника и NSExtensionAttributes разверните NSExtension ключи в редакторе:

IntentsSupported Разверните ключ и добавьте имя любого класса намерений, который будет поддерживаться. Например, приложение MonkeyChat поддерживает INSendMessageIntent:

Если приложению необязательно требуется, чтобы пользователь вошел в систему на устройстве, чтобы использовать заданное намерение, разверните IntentRestrictedWhileLocked ключ и добавьте имена классов намерений с ограниченным доступом. Для примера приложения MonkeyChat пользователь должен войти в систему, чтобы отправить сообщение чата, поэтому мы добавили INSendMessageIntent:

Полный список доступных доменов намерений см. в справочнике по доменам намерений Apple.

Настройка основного класса

Затем разработчику потребуется настроить основной класс, который выступает в качестве основной точки входа для расширения намерения в Siri. Он должен быть подклассом INExtension , который соответствует делегату IINIntentHandler . Например:

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
        ...
    }
}

Существует одиночный метод, который приложение должно реализовать в основном классе Расширения намерения, GetHandler метод. Этот метод передает намерение SiriKit, и приложение должно возвращать обработчик намерений, соответствующий типу данного намерения.

Так как пример приложения MonkeyChat обрабатывает только одно намерение, он возвращается в методе GetHandler . Если расширение обрабатывало несколько намерений, разработчик добавит класс для каждого типа намерения и возвращает экземпляр здесь на Intent основе переданного метода.

Обработка этапа разрешения

Этап разрешения — это место, в котором расширение намерения будет уточнять и проверять параметры, переданные из Siri, и были заданы с помощью беседы пользователя.

Для каждого параметра, который отправляется из Siri, существует Resolve метод. Приложению потребуется реализовать этот метод для каждого параметра, которому может потребоваться помощь Siri для получения правильного ответа от пользователя.

В случае примера приложения MonkeyChat расширение намерения потребует от одного или нескольких получателей отправить сообщение. Для каждого получателя в списке расширение потребуется выполнить поиск контактов, который может иметь следующий результат:

  • Найден ровно один соответствующий контакт.
  • Найдены два или более соответствующих контактов.
  • Не найдены соответствующие контакты.

Кроме того, в MonkeyChat требуется содержимое для текста сообщения. Если пользователь этого не предоставил, Siri должен запрашивать у пользователя содержимое.

Расширение намерения должно будет корректно обрабатывать каждый из этих случаев.

[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);
}

Дополнительные сведения см. в справочнике по этапу разрешения и обработке намерений Apple.

Обработка этапа подтверждения

Этап подтверждения заключается в том, что расширение намерения проверка, чтобы убедиться, что у него есть все сведения для выполнения запроса пользователя. Приложение хочет отправить подтверждение вместе со всеми вспомогательными сведениями о том, что произойдет с Siri, чтобы его можно было подтвердить с пользователем, что это предполагаемое действие.

[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);
}

Дополнительные сведения см. в нашем справочнике по этапу подтверждения.

Обработка намерения

Это точка, в которой расширение намерения фактически выполняет задачу для выполнения запроса пользователя и передачи результатов обратно в Siri, чтобы пользователь смог получить информацию.

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);
}

Дополнительные сведения см. в справочнике по этапу дескриптора.

Добавление расширения пользовательского интерфейса "Намерения"

Дополнительное расширение пользовательского интерфейса "Намерения" представляет возможность перенести пользовательский интерфейс приложения и фирменную символику в интерфейс Siri и сделать пользователей подключенными к приложению. С помощью этого расширения приложение может перенести бренд, а также визуальную и другую информацию в расшифровку.

Пример выходных данных расширения пользовательского интерфейса

Как и расширение "Намерения", разработчик выполнит следующий шаг для расширения пользовательского интерфейса "Намерения".

  • Добавьте проект расширения пользовательского интерфейса "Намерения" в решение приложения Xamarin.iOS.
  • Настройте файл расширения Info.plist пользовательского интерфейса "Намерения".
  • Измените основной класс расширения пользовательского интерфейса "Намерения".

Дополнительные сведения см. в справочнике по расширению пользовательского интерфейса "Намерения", а также в приложении Apple , где предоставляется справочник по пользовательскому интерфейсу.

Создание расширения

Чтобы добавить расширение пользовательского интерфейса "Намерения" в решение, сделайте следующее:

  1. Щелкните правой кнопкой мыши имя решения на панели решения и выберите добавить>новый проект....

  2. В диалоговом окне выберите расширение пользовательского интерфейса намерения расширений>iOS>и нажмите кнопку "Далее".

    Выбор расширения пользовательского интерфейса намерения

  3. Затем введите имя расширения намерения и нажмите кнопку "Далее ":

    Введите имя расширения намерения в Visual Studio для Mac.

  4. Наконец, нажмите кнопку "Создать ", чтобы добавить расширение намерения в решение приложений:

    Добавьте расширение намерения в решение приложений в Visual Studio для Mac.

  5. В Обозреватель решений щелкните правой кнопкой мыши папку "Ссылки" только что созданного расширения намерения. Проверьте имя проекта общей библиотеки кода (созданного выше приложения) и нажмите кнопку ОК :

    Выберите имя проекта общей библиотеки кода в Visual Studio для Mac.

Настройка info.plist

Настройте файл расширения пользовательского интерфейса "Намерения" Info.plist для работы с приложением.

Как и любое типичное расширение приложения, приложение будет иметь существующие ключи NSExtension и NSExtensionAttributes. Для расширения "Намерения" есть один новый атрибут, который необходимо настроить:

Один новый атрибут, который необходимо настроить

НамерениеSupported является обязательным и состоит из массива имен классов намерений, которые приложение должно поддерживать из расширения намерения.

Чтобы настроить файл расширения Info.plist пользовательского интерфейса намерения, дважды щелкните его в Обозреватель решений, чтобы открыть его для редактирования. Затем перейдите к представлению источника и NSExtensionAttributes разверните NSExtension ключи в редакторе:

Ключи NSExtension и NSExtensionAttributes в редакторе.

IntentsSupported Разверните ключ и добавьте имя любого класса намерений, который будет поддерживаться. Например, приложение MonkeyChat поддерживает INSendMessageIntent:

Полный список доступных доменов намерений см. в справочнике по доменам намерений Apple.

Настройка основного класса

Настройте основной класс, который выступает в качестве основной точки входа для расширения пользовательского интерфейса намерения в Siri. Он должен быть подклассом UIViewController , который соответствует интерфейсу IINUIHostedViewController . Например:

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 передает INInteraction экземпляр класса методу UIViewController экземпляра Configure внутри расширения пользовательского интерфейса намерения.

Объект INInteraction предоставляет три ключевых фрагмента информации для расширения:

  1. Обрабатываемый объект Intent.
  2. Объект "Ответ намерения" из Confirm и Handle методов расширения намерения.
  3. Состояние взаимодействия, определяющее состояние взаимодействия между приложением и Siri.

Экземпляр UIViewController является классом принципов взаимодействия с Siri, так как он наследует от UIViewController, он имеет доступ ко всем функциям UIKit.

Когда Siri вызывает Configure метод UIViewController его передачи в контексте представления, указывая, что контроллер представления будет размещен в Siri Snippit или Карты Card.

Siri также будет передавать обработчик завершения, который приложению необходимо вернуть требуемый размер представления после завершения настройки приложения.

Проектирование пользовательского интерфейса в конструкторе iOS

Макет пользовательского интерфейса расширения намерений в конструкторе iOS. Дважды щелкните файл расширения MainInterface.storyboard в Обозреватель решений, чтобы открыть его для редактирования. Перетащите все необходимые элементы пользовательского интерфейса для сборки пользовательского интерфейса и сохранения изменений.

Внимание

Хотя можно добавить интерактивные элементы, такие как или UITextFields в расширение UIViewControllerпользовательского интерфейса намерения, они строго запрещены, так как UIButtons пользовательский интерфейс намерения в неинтерактивном режиме, и пользователь не сможет взаимодействовать с ними.

Подключение пользовательского интерфейса

В пользовательском интерфейсе расширения пользовательского интерфейса "Намерения", созданном в конструкторе iOS, измените UIViewController подкласс и переопределите Configure метод следующим образом:

[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 ();
}

Переопределение пользовательского интерфейса Siri по умолчанию

Расширение пользовательского интерфейса "Намерения" всегда будет отображаться вместе с другим содержимым Siri, таким как значок приложения и имя в верхней части пользовательского интерфейса или в зависимости от намерения, кнопки (например, отправка или отмена) могут отображаться в нижней части экрана.

Существует несколько экземпляров, в которых приложение может заменить сведения, отображаемые пользователем Siri по умолчанию, например обмен сообщениями или карты, где приложение может заменить интерфейс по умолчанию одним, адаптированным к приложению.

Если расширение пользовательского интерфейса "Намерения" должно переопределить элементы пользовательского интерфейса Siri по умолчанию, UIViewController подкласс должен реализовать IINUIHostedViewSiriProviding интерфейс и принять участие в отображении определенного элемента интерфейса.

Добавьте следующий код в UIViewController подкласс, чтобы сообщить Siri, что расширение пользовательского интерфейса намерения уже отображает содержимое сообщения:

public bool DisplaysMessage {
    get {return true;}
}

Рекомендации

Apple предлагает разработчику учитывать следующие аспекты при разработке и реализации расширений пользовательского интерфейса намерения:

  • Учитывайте использование памяти. Так как расширения пользовательского интерфейса намерения являются временными и отображаются только в течение короткого времени, система накладывает более жесткие ограничения памяти, чем используется с полным приложением.
  • Рассмотрим минимальные и максимальные размеры представлений. Убедитесь, что расширения пользовательского интерфейса намерения выглядят хорошо на каждом типе устройства iOS, размере и ориентации. Кроме того, требуемый размер, который приложение отправляет обратно в Siri, может не быть предоставлено.
  • Используйте гибкие и адаптивные шаблоны макета . Опять же, чтобы пользовательский интерфейс выглядел отлично на каждом устройстве.

Итоги

В этой статье рассматривается SiriKit и показано, как его можно добавить в приложения Xamarin.iOS для предоставления служб, доступных пользователю с помощью Siri и приложения Карты на устройстве iOS.