Бөлісу құралы:


Сочетания клавиш Siri в Xamarin.iOS

В iOS 10 Apple представила SiriKit, что позволяет создавать сообщения, voIP звонки, платежи, тренировки, резервирование езды и приложения поиска фотографий, взаимодействующие с Siri.

В iOS 11 SiriKit получила поддержку дополнительных типов приложений и большей гибкости для настройки пользовательского интерфейса.

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

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

Пример приложения: Суп Шеф-повар

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

Совет

Перед тестированием супа Chef на симуляторе или устройстве iOS 12 включите следующие два параметра, которые полезны при отладке ярлыков:

  • В приложении Параметры включите последние сочетания клавиш разработчика>.
  • В приложении Параметры включите пожертвования разработчика > на экране блокировки.

Эти параметры отладки упрощают поиск недавно созданных (вместо прогнозируемых) ярлыков на экране блокировки iOS и экране поиска.

Чтобы использовать пример приложения, выполните следующие действия.

  • Установите и запустите пример приложения Soup Chef на симуляторе или устройстве iOS 12.
  • + Нажмите кнопку в правом верхнем углу, чтобы создать новый заказ.
  • Выберите тип супа, укажите количество и параметры и нажмите кнопку "Разместить заказ".
  • На экране журнала заказов коснитесь только что созданного заказа, чтобы просмотреть его сведения.
  • В нижней части экрана сведений о заказе нажмите кнопку "Добавить в Siri".
  • Запишите голосовую фразу, чтобы связаться с заказом и коснитесь кнопки "Готово".
  • Сведите к минимуму суп Шеф-повар, вызовите Siri и снова поместите заказ с помощью записанной голосовой фразы.
  • После завершения заказа Siri снова откройте суп Шеф-повар и обратите внимание, что новый заказ отображается на экране журнала заказов.

Пример приложения демонстрирует, как:

Info.plist и Entitlements.plist

Прежде чем углубиться в код супа Chef, ознакомьтесь с его файлами Info.plist и Entitlements.plist.

Info.plist

Файл Info.plist в проекте SoupChef определяет идентификатор пакета как com.xamarin.SoupChef. Этот идентификатор пакета будет использоваться в качестве префикса для идентификаторов пакетов расширений пользовательского интерфейса "Намерения и намерения", описанных далее в этом документе.

Файл Info.plist также содержит следующую запись:

<key>NSUserActivityTypes</key>
<array>
    <string>OrderSoupIntent</string>
    <string>com.xamarin.SoupChef.viewMenu</string>
</array>

Эта NSUserActivityTypes пара "ключ-значение" указывает, что Суп Шеф-повар знает, как обрабатывать OrderSoupIntentи NSUserActivity иметь ActivityType "com.xamarin.SoupChef.viewMenu".

Действия и пользовательские намерения, передаваемые самому приложению, в отличие от его расширений, обрабатываются в AppDelegate (методе UIApplicationDelegateContinueUserActivity ).

Entitlements.plist

Файл Entitlements.plist в проекте SoupChef содержит следующие записи:

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.xamarin.SoupChef</string>
</array>
<key>com.apple.developer.siri</key>
<true/>

Эта конфигурация указывает, что приложение использует группу приложений group.com.xamarin.SoupChef. Расширение приложения SoupChefIntents использует ту же группу приложений, которая позволяет двум проектам совместно использовать NSUserDefaults Данных.

Ключ com.apple.developer.siri указывает, что приложение взаимодействует с Siri.

Примечание.

Конфигурация сборки проекта SoupChef задает настраиваемые права на права для прав.plist.

Использование ярлыка NSUserActivity для открытия приложения

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

Настройка NSUserActivity

На экране SoupMenuViewController меню создается NSUserActivity и назначается свойству контроллера UserActivity представления:

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    UserActivity = NSUserActivityHelper.ViewMenuActivity;
}

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

NSUserActivityHelper — это класс служебной программы, включенный в решение SoupChef , в библиотеке классов SoupKit . Он создает NSUserActivity и задает различные свойства, связанные с Siri и поиском:

public static string ViewMenuActivityType = "com.xamarin.SoupChef.viewMenu";

public static NSUserActivity ViewMenuActivity {
    get
    {
        var userActivity = new NSUserActivity(ViewMenuActivityType)
        {
            Title = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_TITLE", "View menu activity title"),
            EligibleForSearch = true,
            EligibleForPrediction = true
        };

        var attributes = new CSSearchableItemAttributeSet(NSUserActivityHelper.SearchableItemContentType)
        {
            ThumbnailData = UIImage.FromBundle("tomato").AsPNG(),
            Keywords = ViewMenuSearchableKeywords,
            DisplayName = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_TITLE", "View menu activity title"),
            ContentDescription = NSBundleHelper.SoupKitBundle.GetLocalizedString("VIEW_MENU_CONTENT_DESCRIPTION", "View menu content description")
        };
        userActivity.ContentAttributeSet = attributes;

        var phrase = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_SUGGESTED_PHRASE", "Voice shortcut suggested phrase");
        userActivity.SuggestedInvocationPhrase = phrase;
        return userActivity;
    }
}

Обратите внимание на следующие особенности:

  • Параметр EligibleForPrediction , указывающий true , что Siri может прогнозировать это действие и отображать его как ярлык.
  • Массив ContentAttributeSet — это стандарт CSSearchableItemAttributeSet , используемый для включения NSUserActivity в результаты поиска iOS.
  • SuggestedInvocationPhrase — это фраза, которую Siri предложит пользователю в качестве потенциального выбора при назначении фразы ярлыку.

Обработка ярлыка NSUserActivity

Для обработки NSUserActivity ярлыка, вызываемого пользователем, приложение iOS должно переопределить ContinueUserActivity метод AppDelegate класса, отвечая на ActivityType поле переданного NSUserActivity объекта:

public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
    // ...
    else if (userActivity.ActivityType == NSUserActivityHelper.ViewMenuActivityType)
    {
        HandleUserActivity();
        return true;
    }
    // ...
}

Этот метод вызывает HandleUserActivityметод, который находит сеге на экране меню и вызывает его:

void HandleUserActivity()
{
    var rootViewController = Window?.RootViewController as UINavigationController;
    var orderHistoryViewController = rootViewController?.ViewControllers?.FirstOrDefault() as OrderHistoryTableViewController;
    if (orderHistoryViewController is null)
    {
        Console.WriteLine("Failed to access OrderHistoryTableViewController.");
        return;
    }
    var segue = OrderHistoryTableViewController.SegueIdentifiers.SoupMenu;
    orderHistoryViewController.PerformSegue(segue, null);
}

Назначение фразы NSUserActivity

Чтобы назначить фразуNSUserActivity, откройте приложение iOS Параметры и выберите Siri и поиск > моих ярлыков. Затем выберите ярлык (в данном случае "Заказать обед") и запишите фразу.

Вызов Siri и использование этой фразы откроет суп Шеф-повар на экране меню.

Использование ярлыка пользовательского намерения для выполнения задачи

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

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

Используйте Xcode 10 для создания пользовательских намерений. В репозитории SoupChef настраиваемое намерение определяется в OrderSoupIntentCodeGen, проектеObjective-C. Откройте этот проект и выберите файл Intents.intentdefinition в навигаторепроекта, чтобы просмотреть намерение OrderSoup.

Обратите внимание на следующие возможности.

  • Намерение имеет категориюзаказа. Существуют различные предварительно определенные категории, которые можно использовать для пользовательских намерений; Выберите тот, который наиболее тесно соответствует задаче, которую будет включать пользовательское намерение. Так как это решение является приложением для заказа супа, OrderSoupIntent использует Order.
  • Поле "Подтверждение" проверка box указывает, должен ли Siri запрашивать подтверждение перед выполнением задачи. Для намерения Order Soup в Суп Шеф-поваре этот параметр включен, так как пользователь делает покупку.
  • Раздел "Параметры" файла намерения определяет параметры, относящиеся к ярлыку. Чтобы разместить заказ супа, Суп Шеф-повар должен знать тип супа, его количество и любые связанные варианты. Каждый параметр имеет тип; параметр, который не может быть представлен предопределенным типом, имеет значение Custom.
  • Интерфейс сочетаний клавиш описывает различные сочетания параметров Siri, которые можно использовать при выборе ярлыка. Связанные разделы заголовок и субтитры позволяют определить сообщения Siri, которые будут использоваться при представлении предлагаемого ярлыка пользователю.
  • Поле "Поддержка фонового выполнения" проверка должно быть выбрано для любого ярлыка, который можно выполнить без открытия приложения для дальнейшего взаимодействия с пользователем.

Определение пользовательских ответов намерений

Элемент ответа , вложенный под намерением OrderSoup , представляет потенциальные ответы, результатом чего является порядок супа.

В определении ответа намерения OrderSoup обратите внимание на следующие функции:

  • Свойства ответа можно использовать для настройки сообщения, переданного пользователю. Ответ намерения OrderSoup имеет свойства супа и waitTime .
  • Шаблоны ответов указывают различные сообщения об успешном выполнении и сбое, которые можно использовать для указания состояния после завершения задачи намерения.
  • Поле "Успех" проверка должно быть выбрано для ответов, указывающих на успешность.
  • Ответ на успешное выполнение OrderSoupIntent использует свойства супа и waitTime, чтобы предоставить понятное и полезное сообщение, описывающее, когда заказ супа будет готов.

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

Создание проекта Xcode, содержащего это определение пользовательского намерения, приводит к созданию Xcode кода, который можно использовать для программного взаимодействия с пользовательским намерением и его ответами.

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

  • Откройте AppDelegate.m.
  • Добавьте импорт в файл заголовка пользовательского намерения: #import "OrderSoupIntent.h"
  • В любом методе класса добавьте ссылку OrderSoupIntentна .
  • Щелкните правой кнопкой мыши OrderSoupIntent и выберите пункт "Перейти к определению".
  • Щелкните правой кнопкой мыши новый открытый файл OrderSoupIntent.h и выберите "Показать в Finder".
  • Это действие откроет окно Finder, содержащее файл H и M, содержащий созданный код.

Этот созданный код включает:

  • OrderSoupIntent — класс, представляющий пользовательское намерение.
  • OrderSoupIntentHandling — протокол, определяющий методы, которые будут использоваться для подтверждения того, что намерение должно быть выполнено, и метод, который фактически выполняет его.
  • OrderSoupIntentResponseCode — перечисление, определяющее различные состояния ответа.
  • OrderSoupIntentResponse — класс, представляющий ответ на выполнение намерения.

Создание привязки к пользовательскому намерению

Чтобы использовать код, созданный Xcode в приложении Xamarin.iOS, создайте для него привязку C#.

Создание статической библиотеки и определений привязки C#

В репозитории SoupChef просмотрите папку OrderSoupIntentStaticLib и откройте проект OrderSoupIntentStaticLib.xcodeproj Xcode.

Этот проект статической библиотеки Cocoa Touch содержит файлы OrderSoupIntent.h и OrderSoupIntent.m , созданные Xcode.

Настройка параметров сборки проекта статической библиотеки

В навигаторе проекта Xcode выберите проект верхнего уровня OrderSoupIntentStaticLib и перейдите к источникам компиляции этапов сборки>. Обратите внимание, что OrderSoupIntent.m (который импортирует OrderSoupIntent.h) указан здесь. Обратите внимание, что в библиотеки link binary with libraries содержатся намерения.framework и Foundation.framework. При использовании этих параметров платформа будет правильно создаваться.

Создание статической библиотеки и создание определений привязок C#

Чтобы создать статическую библиотеку и создать определения привязок C#, выполните следующие действия.

  • Установите Objective Sharpie, средство, используемое для создания определений привязок из файлов H и M , созданных Xcode.

  • Настройте систему для использования средств командной строки Xcode 10:

    Предупреждение

    Обновление выбранных средств командной строки влияет на все установленные версии Xcode в системе. Когда вы закончите работу с примером приложения "Суп Шеф-повар", обязательно отменить изменения этот параметр в исходной конфигурации.

    • В Xcode выберите расположения параметров> Xcode > и установите средства командной строки для самой текущей установки Xcode 10, доступной в вашей системе.
  • В терминале cd в каталог OrderSoupIntentStaticLib .

  • Тип make, который создает:

    • Статическая библиотека, libOrderSoupIntentStaticLib.a
    • В выходном каталоге bo определения привязок C#:
      • ApiDefinitions.cs
      • StructsAndEnums.cs

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

Дополнительные сведения о создании статической библиотеки и использовании Objective Sharpie для создания определений привязок C# см. в пошаговом руководстве по привязке библиотеки iOSObjective-C.

Создание библиотеки привязок

При создании статической библиотеки и определений привязок C# оставшаяся часть, необходимая для использования кода, связанного с намерением Xcode, в проекте Xamarin.iOS является библиотекой привязок.

В репозитории Soup Chef откройте файл SoupChef.sln. Помимо прочего, это решение содержит OrderSoupIntentBinding, библиотеку привязок для статической библиотеки, созданной ранее.

Обратите внимание, что этот проект включает:

  • ApiDefinitions.cs — файл, созданный ранее objective Sharpie и добавленный в этот проект. Действие сборки этого файла имеет значение ObjcBindingApiDefinition.

  • StructsAndEnums.cs — другой файл, созданный ранее Objective Sharpie и добавленный в этот проект. Действие сборки этого файла имеет значение ObjcBindingCoreSource.

  • Собственная ссылка на libOrderSoupIntentStaticLib.a, статическая библиотека, созданная ранее. Обновите собственные свойства ссылок и укажите следующие значения:

    1. Frameworks = Foundation Intents
    2. Smart Link = On
    3. Force Load = On
    4. Kind = Static

Примечание.

Оба ApiDefinitions.cs и StructsAndEnums.cs содержат такие атрибуты, как [Watch (5,0), iOS (12,0)]. Эти атрибуты, созданные Objective Sharpie, были закомментированы, так как они не нужны для этого проекта.

Дополнительные сведения о создании библиотеки привязок C# см. в пошаговом руководстве по привязке библиотеки iOSObjective-C.

Обратите внимание, что проект SoupChef содержит ссылку на OrderSoupIntentBinding, что означает, что теперь он может получить доступ к классам, интерфейсам и перечислениям, содержащим:

  • OrderSoupIntent
  • OrderSoupIntentHandling
  • OrderSoupIntentResponse
  • OrderSoupIntenseResponseCode

Создание платформы Swift

Машинный код определения намерения создается Xcode по умолчанию с помощью языка собственного проекта. Если вы определяете файл Intents.intentdefinition в проекте Swift, Xcode создаст один файл Swift со всеми необходимыми классами, которые можно использовать для создания платформы Swift.

Совет

Вы можете выбрать нужный язык для созданного кода намерения в параметрах сборки Xcode. Перейдите к целевой сборке намерения > Параметры > компилятор определения намерения — создание кода и выберите Swift или Objective-C. Вы также можете сохранить его автоматически, чтобы соответствовать целевому языку.

Процесс создания платформы Swift аналогичен описанному ранее:

  1. Создайте проект платформы Swift.
  2. Скопируйте автоматически созданный файл Swift с кодом намерения в этот проект, как описано здесь.
  3. Objective-C Включите заголовок бриджинга, поэтому платформа автоматически создается с необходимым Objective-C файлом заголовка Sharpie.

После создания платформы выполните те же действия , описанные ранее, чтобы создать привязку Xamarin. Дополнительные сведения о создании привязки для платформы Swift см. здесь.

Добавление файла определения намерения в решение

В решении C# SoupChef проект SoupKit содержит код, общий доступ между приложением и его расширениями. Файл Intents.intentdefinition был помещен в каталог Base.lproj в СупКит, и имеет действие сборки содержимого. Процесс сборки копирует этот файл в пакет приложений Soup Chef, где он необходим для правильной работы приложения.

Пожертвование намерения

Чтобы Siri предложил ярлык, он должен сначала понять, когда ярлык имеет значение.

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

СупЧеф использует SoupOrderDataManager класс для размещения пожертвований. При вызове для размещения заказа супа для пользователя PlaceOrder метод в свою очередь вызывает DonateInteraction:

void DonateInteraction(Order order)
{
    var interaction = new INInteraction(order.Intent, null);
    interaction.Identifier = order.Identifier.ToString();
    interaction.DonateInteraction((error) =>
    {
        // ...
    });
}

После получения намерения он упаковывается в INInteractionобъект. Дано INInteraction значение Identifier это соответствует уникальному идентификатору заказа (это будет полезно позже при удалении пожертвований намерений, которые больше не являются допустимыми). Затем взаимодействие пожертвовано Siri.

Вызов order.Intent getter извлекает объектOrderSoupIntent, представляющий порядок, задав его Quantity, SoupOptionsи изображение, и фразу вызова, которая будет использоваться в качестве предложения, когда пользователь записывает фразу для Siri, чтобы связаться с намерением:

public OrderSoupIntent Intent
{
    get
    {
        var orderSoupIntent = new OrderSoupIntent();
        orderSoupIntent.Quantity = new NSNumber(Quantity);
        orderSoupIntent.Soup = new INObject(MenuItem.ItemNameKey, MenuItem.LocalizedString);

        var image = UIImage.FromBundle(MenuItem.IconImageName);
        if (!(image is null))
        {
            var data = image.AsPNG();
            orderSoupIntent.SetImage(INImage.FromData(data), "soup");
        }

        orderSoupIntent.Options = MenuItemOptions
            .ToArray<MenuItemOption>()
            .Select<MenuItemOption, INObject>(arg => new INObject(arg.Value, arg.LocalizedString))
            .ToArray<INObject>();

        var comment = "Suggested phrase for ordering a specific soup";
        var phrase = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_SOUP_SUGGESTED_PHRASE", comment);
        orderSoupIntent.SuggestedInvocationPhrase = String.Format(phrase, MenuItem.LocalizedString);

        return orderSoupIntent;
    }
}

Удаление недопустимых пожертвований

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

В супе Chef экран "Настройка меню " можно использовать для пометки элемента меню как недоступного. Siri больше не должен предлагать ярлык для заказа недоступного элемента меню, поэтому RemoveDonation метод SoupMenuManager удаления пожертвований для элементов меню, которые больше не доступны. Приложение реализует эту функцию следующим образом:

  • Поиск заказов, связанных с недоступным элементом меню.
  • Захват идентификаторов.
  • Удаление взаимодействий с одинаковыми идентификаторами.
void RemoveDonation(MenuItem menuItem)
{
    if (!menuItem.IsAvailable)
    {
        Order[] orderHistory = OrderManager?.OrderHistory.ToArray<Order>();
        if (orderHistory is null)
        {
            return;
        }

        string[] orderIdentifiersToRemove = orderHistory
            .Where<Order>((order) => order.MenuItem.ItemNameKey == menuItem.ItemNameKey)
            .Select<Order, string>((order) => order.Identifier.ToString())
            .ToArray<string>();

        INInteraction.DeleteInteractions(orderIdentifiersToRemove, (error) =>
        {
            if (!(error is null))
            {
                Console.WriteLine($"Failed to delete interactions with error {error.ToString()}");
            }
            else
            {
                Console.WriteLine("Successfully deleted interactions");
            }
        });
    }
}

Проверка успешных пожертвований

Решение включает несколько проектов и определенную конфигурацию. В некоторых случаях приложение может завершиться сбоем из-за неполной конфигурации, в других случаях оно может автоматически завершить работу. Важно проверить успешные пожертвования и параметры разработчика iOS. Перейдите к Параметры > разработчику и включите следующие параметры разработчика, чтобы просмотреть последние пожертвования и сочетания клавиш:

  • Отображение последних ярлыков
  • Отображение пожертвований на экране блокировки

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

  1. Не удается создать приложение со следующей ошибкой OrderSoupIntent :

    Не удалось создать собственный экземпляр типа NativeLibrary.OrderSoupIntent: собственный класс не был загружен.

    Эта ошибка означает, что Xamarin не может загрузить собственный класс через привязку Xamarin. Чтобы исправить это, убедитесь, что в машинной библиотеке есть обязательный код, на который ссылается проект привязки, и установлены соответствующие флаги, как описано здесь, задайте для флага Force LoadOnзначение .

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

    Не удалось инициализировать экземпляр типа NativeLibrary.OrderSoupIntent: собственный метод init вернул nil.

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

  3. Приложение создает намерение и вызывает метод пожертвования без сбоя, но выходные данные консоли показывают предупреждение о неизвестном типе намерения и не выполняется пожертвование:

    Не удается выполнить взаимодействие с OrderSoupIntent без допустимых типов ярлыков

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

    Info.plist приложения:

    <key>NSUserActivityTypes</key>
    <array>
        <string>ScheduleMeetingIntent</string>
    </array>
    

    Список прав.plist приложения с возможностью Siri:

    <key>com.apple.developer.siri</key>
    <true/>
    

    Пользовательские права должны быть выбраны для целевой конфигурации сборки. Перейдите в раздел "Параметры проекта" Сборка >> подписи пакета iOS и задайте настраиваемые права на файл "Права.plist", содержащий необходимые права.

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

Код, который выполняется при вызове Siri намерения, помещается в расширение "Намерения", который можно добавить в качестве нового проекта в то же решение, что и существующее приложение Xamarin.iOS, например Soup Chef. В решении SoupChef расширение называется SoupChefIntents.

SoupChefIntents — Info.plist и Entitlements.plist

SoupChefIntents — Info.plist

Info.plist в проекте SoupChefIntents определяет идентификатор пакета как com.xamarin.SoupChef.SoupChefIntents.

Файл Info.plist также содержит следующую запись:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>IntentsRestrictedWhileLocked</key>
        <array/>
        <key>IntentsSupported</key>
        <array>
            <string>OrderSoupIntent</string>
        </array>
        <key>IntentsRestrictedWhileProtectedDataUnavailable</key>
        <array/>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.intents-service</string>
    <key>NSExtensionPrincipalClass</key>
    <string>IntentHandler</string>
</dict>

В приведенном выше файле Info.plist:

  • IntentsRestrictedWhileLocked перечисляет намерения обрабатываться при разблокировке устройства.
  • IntentsSupported перечисляет намерения, обрабатываемые этим расширением.
  • NSExtensionPointIdentifier указывает тип расширения приложения. Дополнительные сведения см . в документации Apple.
  • NSExtensionPrincipalClass указывает класс, который следует использовать для обработки намерений, поддерживаемых этим расширением.
SoupChefIntents — Entitlements.plist

В проекте SoupChefIntents есть возможность "Группы приложений". Эта возможность настроена для использования той же группы приложений, что и проект SoupChef :

<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.xamarin.SoupChef</string>
</array>

Суп Шеф-повар сохраняет данные с NSUserDefaults. Чтобы предоставить общий доступ к данным между приложением и расширением приложения, они ссылаются на ту же группу приложений в файлах Entitlements.plist .

Примечание.

Конфигурация сборки проекта SoupChefIntents задает пользовательские права на разрешения на разрешения.plist.

Обработка фоновой задачи OrderSoupIntent

Расширение "Намерения" выполняет необходимые фоновые задачи для ярлыка на основе пользовательского намерения.

Siri вызывает GetHandler метод IntentHandler класса (определенный в Info.plist в качестве ) NSExtensionPrincipalClass, чтобы получить экземпляр класса, который расширяется OrderSoupIntentHandling, который можно использовать для обработки OrderSoupIntent:

[Register("IntentHandler")]
public class IntentHandler : INExtension
{
    public override NSObject GetHandler(INIntent intent)
    {
        if (intent is OrderSoupIntent)
        {
            return new OrderSoupIntentHandler();
        }
        throw new Exception("Unhandled intent type: ${intent}");
    }

    protected IntentHandler(IntPtr handle) : base(handle) { }
}

OrderSoupIntentHandler, определенный в проекте SoupKit общего кода, реализует два важных метода:

  • ConfirmOrderSoup — подтверждает, должна ли фактически выполняться задача, связанная с намерением.
  • HandleOrderSoup — помещает порядок супа и отвечает пользователю путем вызова переданного обработчика завершения

Обработка OrderSoupIntent, открывающего приложение

Приложение должно правильно обрабатывать намерения, которые не выполняются в фоновом режиме. Эти намерения обрабатываются так же, как NSUserActivity и сочетания клавиш, в методе ContinueUserActivityAppDelegate:

public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
    var intent = userActivity.GetInteraction()?.Intent as OrderSoupIntent;
    if (!(intent is null))
    {
        HandleIntent(intent);
        return true;
    }
    // ...
}  

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

Расширение пользовательского интерфейса "Намерения" предоставляет пользовательский интерфейс для расширения "Намерения". В решении SoupChef СупШеф это расширение пользовательского интерфейса Intents, которое предоставляет интерфейс для SoupChefIntents.

SoupChefIntentsUI — Info.plist и Entitlements.plist

SoupChefIntentsUI — Info.plist

Info.plist в проекте SoupChefIntentsUI определяет идентификатор пакета как com.xamarin.SoupChef.SoupChefIntentsui.

Файл Info.plist также содержит следующую запись:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>IntentsSupported</key>
        <array>
            <string>OrderSoupIntent</string>
        </array>
        <!-- ... -->
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.intents-ui-service</string>
    <key>NSExtensionMainStoryboard</key>
    <string>MainInterface</string>
</dict>

В приведенном выше файле Info.plist:

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

SoupChefIntentsUI — Entitlements.plist

Для проекта SoupChefIntentsUI не требуется файл Entitlements.plist .

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

Так как Info.plist для SoupChefIntentsUI задает NSExtensionMainStoryboard для ключа значениеMainInterface, файл MainInterace.storyboard определяет интерфейс для расширения пользовательского интерфейса "Намерения".

В этой раскадровки есть один контроллер представления типа IntentViewController. Он ссылается на два представления:

  • invoiceView, тип InvoiceView
  • confirmationView, тип ConfirmOrderView

Примечание.

Интерфейсы для выставления счетов и подтвержденияView определяются в Main.storyboard как вторичные представления. Visual Studio для Mac и Visual Studio 2017 не поддерживают просмотр или редактирование вторичных представлений; для этого откройте Main.storyboard в построителе интерфейсов Xcode.

IntentViewController реализует IINUIHostedViewControlling интерфейс, используемый для предоставления пользовательского интерфейса при работе с намерениями Siri. Токен ConfigureViewМетод вызывается для настройки интерфейса, отображения подтверждения или счета в зависимости от того, выполняется ли взаимодействие () или выполнено успешно (INIntentHandlingStatus.ReadyINIntentHandlingStatus.Success):

[Export("configureViewForParameters:ofInteraction:interactiveBehavior:context:completion:")]
public void ConfigureView(
    NSSet<INParameter> parameters,
    INInteraction interaction,
    INUIInteractiveBehavior interactiveBehavior,
    INUIHostedViewContext context,
    INUIHostedViewControllingConfigureViewHandler completion)
{
    // ...
    if (interaction.IntentHandlingStatus == INIntentHandlingStatus.Ready)
    {
        desiredSize = DisplayInvoice(order, intent);
    }
    else if(interaction.IntentHandlingStatus == INIntentHandlingStatus.Success)
    {
        var response = interaction.IntentResponse as OrderSoupIntentResponse;
        if (!(response is null))
        {
            desiredSize = DisplayOrderConfirmation(order, intent, response);
        }
    }
    completion(true, parameters, desiredSize);
}

Совет

Дополнительные сведения о методе см. в презентации ConfigureView Apple WWDC 2017, What's New in SiriKit.

Создание сочетания клавиш для голосовой связи

Суп Шеф-повар предоставляет интерфейс для назначения голосового ярлыка каждому заказу, что позволяет заказать суп с Siri. На самом деле интерфейс, используемый для записи и назначения сочетаний клавиш голосовой связи, предоставляется iOS и требует небольшого пользовательского кода.

Когда OrderDetailViewControllerпользователь нажимает кнопку "Добавить в строку Siri", RowSelected метод представляет экран для добавления или изменения сочетания клавиш голосовой связи:

public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
    // ...
    else if (TableConfiguration.Sections[indexPath.Section].Type == OrderDetailTableConfiguration.SectionType.VoiceShortcut)
    {
        INVoiceShortcut existingShortcut = VoiceShortcutDataManager?.VoiceShortcutForOrder(Order);
        if (!(existingShortcut is null))
        {
            var editVoiceShortcutViewController = new INUIEditVoiceShortcutViewController(existingShortcut);
            editVoiceShortcutViewController.Delegate = this;
            PresentViewController(editVoiceShortcutViewController, true, null);
        }
        else
        {
            // Since the app isn't yet managing a voice shortcut for
            // this order, present the add view controller
            INShortcut newShortcut = new INShortcut(Order.Intent);
            if (!(newShortcut is null))
            {
                var addVoiceShortcutVC = new INUIAddVoiceShortcutViewController(newShortcut);
                addVoiceShortcutVC.Delegate = this;
                PresentViewController(addVoiceShortcutVC, true, null);
            }
        }
    }
}

В зависимости от того, существует ли существующее голосовое сочетание клавиш для текущего отображаемого порядка, RowSelected представляет контроллер представления типа INUIEditVoiceShortcutViewController или INUIAddVoiceShortcutViewController. В каждом случае OrderDetailViewController задает себя в качестве контроллера Delegateпредставления, поэтому он также реализует IINUIAddVoiceShortcutViewControllerDelegate и IINUIEditVoiceShortcutViewControllerDelegate.

Тестирование на устройстве

Чтобы запустить Суп Шеф-повар на устройстве, следуйте инструкциям в этом разделе. Также ознакомьтесь с примечанием о автоматической подготовке.

Группа приложений, идентификаторы приложений, профили подготовки

В разделе "Сертификаты" и "Профили" на портале разработчика Apple сделайте следующее:

  • Создайте группу приложений для совместного использования данных между приложением Soup Chef и его расширениями. Например: group.com.yourcompanyname.SoupChef

  • Создайте три идентификатора приложения: один для самого приложения, один для расширения "Намерения" и один для расширения пользовательского интерфейса "Намерения". Например:

    • Приложение: com.yourcompanyname.SoupChef

      • Для этого идентификатора приложения назначьте возможности SiriKit и группы приложений.
    • Расширение "Намерения": com.yourcompanyname.SoupChef.Intents

      • Для этого идентификатора приложения назначьте возможности групп приложений.
    • Расширение пользовательского интерфейса "Намерения": com.yourcompanyname.SoupChef.Intentsui

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

  • Создайте три новых профиля подготовки разработки, по одному для каждого из новых идентификаторов приложений.

  • Скачайте эти профили подготовки и дважды щелкните каждый из них, чтобы установить его. Если Visual Studio для Mac или Visual Studio 2017 уже запущен, перезапустите его, чтобы убедиться, что он регистрирует новые профили подготовки.

Редактирование Info.plist, Entitlements.plist и исходный код

В Visual Studio для Mac или Visual Studio 2017 выполните следующие действия:

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

    • Приложение: com.yourcompanyname.SoupChef
    • Расширение "Намерения": com.yourcompanyname.SoupChef.Intents
    • Расширение пользовательского интерфейса намерений: com.yourcompanyname.SoupChef.Intentsui
  • Обновите файл Entitlements.plist для проекта SoupChef:

    • Для возможности "Группы приложений" задайте группе новую группу приложений, созданную ранее (в приведенном выше примере она была group.com.yourcompanyname.SoupChef).
    • Убедитесь, что SiriKit включен.
  • Обновите файл Entitlements.plist для проекта SoupChefIntents:

    • Для возможности "Группы приложений" задайте группе новую группу приложений, созданную ранее (в приведенном выше примере она была group.com.yourcompanyname.SoupChef).
  • Наконец, откройте NSUserDefaultsHelper.cs. AppGroup Задайте для переменной значение новой группы приложений (например, задайте для нее значениеgroup.com.yourcompanyname.SoupChef).

Настройка параметров сборки

В Visual Studio для Mac или Visual Studio 2017:

  • Откройте параметры и свойства проекта SoupChef . На вкладке подписывания пакета iOS задайте для удостоверения подписи автоматический профиль подготовки и подготовки нового профиля подготовки для конкретного приложения, созданного ранее.

  • Откройте параметры и свойства проекта SoupChefIntents . На вкладке подписывания пакета iOS задайте для удостоверения подписи автоматический профиль подготовки и подготовки для нового профиля подготовки намерений, созданного ранее.

  • Откройте параметры и свойства проекта SoupChefIntentsUI . На вкладке подписывания пакета iOS задайте для удостоверения подписи автоматический профиль подготовки и подготовки нового профиля подготовки расширения пользовательского интерфейса "Намерения", созданного ранее.

С этими изменениями приложение будет работать на устройстве iOS.

Автоматическая подготовка

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