[iOS 10] Встраиваем поддержку Siri в свое iOS приложение

    image

    Apple показала на WWDC 2016 новые iOS 10 и macOS Sierra, и я не упустил возможность сразу же обновить свои устройста.

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

    (!) Уважаемые читатели «Хабрахабра», все ошибки и правки по данной статье присылайте, пожалуйста, в личные сообщения.


    Мои впечатления от iOS 10 и macOS


    В новой macOS появилась Siri — это сразу бросается в глаза, с новыми функциями. Наконец-то заработал обмен ссылками между iOS и macOS — как только открываешь страницу на iPhone/iPad — сразу появляется на mac значек Safari, открывающий эту страницу (Раньше эта функция работала через раз). Ну и конечно очень круто — что копируя текст на iOS — его можно вставить на macOS. С картинками и фото тоже самое — один клик на iPhone, и фото уже на ноутбуке, больше не нужно мэйлить фото самому себе. По умолчанию включается на macOS телеметрия, которую я сразу отключил (скрин). Из минусов iOS 10 — действительно тормозная, иногда (не всегда) на iPhone 5S и iPad Air подтормаживает скролл, но в целом, интерфейс выглядит более стильно, контрастнее, изменения UI незначительные, но в целом «более стильно и минималистично» :) В плане UI дизайна так же стоит отметить обновленные формочки для IN-APP уведомлений.

    image

    (!) Если кто-то поставил iOS 10, то чтобы в старом xcode (7.3) можно было работать с девайсом, нужно просто из xcode 8.0 в xcode 7.3 скопировать папку «DeviceSupport/10.0» в тоже место.

    Из каталога:
    Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.0 (14A5261u)/
    В папку:
    Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.0 (14A5261u)/


    Apple предлагает несколько сценариев для использования Siri сторонними разработчиками:

    • Аудио и видео звонки
    • Работа с сообщениями и контактами
    • Совершение платежей с помощью Siri
    • Поиск фотографий
    • Тренировки
    • Работа с картами (Вызов такси)


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

    Для начала скачиваем и устанавливаем Xcode 8 и создаем новое приложение с одним ViewController и называем его, например «DemoApp».

    Для добавления голосовой поддержки нам придется добавить новое расширение, для этого выбираем в левой панели файлового менеджера верхнюю строчку (файл проекта) и выбираем в меню Editor -> Add target…

    image

    Назовем наше расширение «DemoAppSiriIntent», так же не забываем проверить наличие галочки напротив «Include UI Extension»

    image

    Так же для работы Siri нам необходимо добавить в проект библиотеку CoreLocation.framework

    image

    У нас в проекте появились новые файлы

    • IntentHandler.m — файл с CallBack функциями, которые возвращает Siri
    • IntentViewController.m — файл для работы с StoryBoard интерфейсом, который расположен рядом, в файле MainInterface.storyboard


    Для начала мы научим наше приложение запускать «Фитнес активность» (Workout), для этого в файле IntentHandler.m должны быть объявленны следущие Delegates:

    @interface IntentHandler () <INStartWorkoutIntentHandling, INPauseWorkoutIntentHandling, INResumeWorkoutIntentHandling, INCancelWorkoutIntentHandling, INEndWorkoutIntentHandling>
    @end
    


    Для обозначения методов взаимодействия с Siri Apple использует слово «Intent», теперь, зажимая клавишу CMD, кликаем на «INStartWorkoutIntentHandling» и смотрим, какие функции использует данный deligate.

    Обязательный для включения в проект метод:

    • handleStartWorkout


    Дополнительные методы, которые можно не включать в проект:

    • confirmStartWorkout
    • resolveWorkoutNameForStartWorkout
    • resolveGoalValueForStartWorkout
    • resolveWorkoutGoalUnitTypeForStartWorkout
    • resolveWorkoutLocationTypeForStartWorkout
    • resolveIsOpenEndedForStartWorkout


    Медод «confirmStartWorkout» вызывает по порядку следущие Callback функции, которые уже автоматически созданы в нашем файле «IntentHandler.m»:

    • resolveWorkoutNameForStartWorkout
    • resolveGoalValueForStartWorkout
    • DemoAppSiriIntent
    • resolveWorkoutLocationTypeForStartWorkout
    • resolveIsOpenEndedForStartWorkout
    • confirmStartWorkout
    • handleStartWorkout


    Рядом с файлом «IntentHandler.m» мы видим plist с настройками нашего «Intent» расширения, «Info.plist».

    Проверяем, что в ветке "NSExtension -> NSExtensionAttributes -> IntentsSupported" перечислены все наши Intents для работы с Siri Workout:

    1. Item 0: INStartWorkoutIntent
    2. Item 1: INPauseWorkoutIntent
    3. Item 2: INResumeWorkoutIntent
    4. Item 3: INCancelWorkoutIntent
    5. Item 4: INEndWorkoutIntent


    image

    Если мы продублируем данные «Intents» в ветку "NSExtension -> NSExtensionAttributes -> IntentsRestrictedWhileLocked", то Siri сможет вызывать функции из нашего приложения даже с заблокированного устройства.

    Теперь переходим к файлу «MainInterface.storyboard» и для демо приложения добавляем на него два UILabel, один из них будет счетчиком, для демонстрации того, что наш UI интерфейс внутри Siri может обновляться в реальном времени.

    image

    Важно отметить, что данный интерфейс не может содержать «gesture recognizers» и перехватчики событий нажатия пальцами и, при закрытии данного окна, Siri освободит все объекты в памяти.

    На следующей схеме мы можем ознакомиться с жизненным циклом нашего «Siri view интерфейса».

    image

    Итак, самое время скомпилировать наше приложение и проверить, работают ли голосовые команды. Тестировать данный пример получится только на реальном устройстве, для начала собираем приложение как обычно:

    image

    Затем нажимаем на Stop и отдельно компилируем наше расширение, выбрав схему «DemoAppSiriIntent». Во время компиляции Xcode спросит нас, для какого приложения мы собираем данное расширение, и в списке мы указываем «DemoApp».

    image

    На этом этапе мы увидим, что наше приложение появляется на секунду и тут же исчезает, это не «вылет», всё функции вывода NSLog из файла «IntentHandler.m» показывают нам, что все работает.

    Ах да, чуть не зыбыл, в настройках нашего iOS девайса заходим в раздел Siri и устанавливаем галочку напротив нашей программы «DemoApp»:

    image

    Итак, самое время произнести вслух «Hey, Siri, start workout in DemoApp»


    Результат вы можете наблюдать на данном видео:



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

    Перейдя по данной ссылке, вы можете ознакомиться со всеми «Intent» методами, которые поддерживаются в данный момент Siri:
    https://developer.apple.com/...

    Сейчас нас интересует секция «Messaging», открываем наш «IntentHandler.m» файл, прописываем delegate для сообщений:

    @interface IntentHandler () <INSendMessageIntentHandling>
    


    Удерживая зажатой CMD — кликаем на «INSendMessageIntentHandling» и видим, что необходимой функцией в этот раз является «handleSendMessage». Для начала присваиваем «Intent» для сообщений в функции «handlerForIntent»:

    - (id)handlerForIntent:(INIntent *)intent {
        id handler = nil;
        if ([intent isKindOfClass:[INSendMessageIntent class]]) {
            handler = self;
        }
        handler = self;
        return handler;
    }
    


    И затем пишем callback функцию для нашего «Intent»:

    - (void)handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse * _Nonnull))completion {
        NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
        INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:
            INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
        NSLog(@"handleSendMessage");
        completion(response);
    }
    


    Не забываем прописать наш новый «Intent» в plist.info, в ветку "NSExtension -> NSExtensionAttributes -> IntentsSupported":

    image

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

    Исходные файлы проекта из данной статьи вы можете скачать по ссылке:

    http://big-lab.com/images/articles/sirikit/DemoApp.zip
    Поделиться публикацией

    Похожие публикации

    Комментарии 19

      +1
      Спасибо за статью. Если можно, то я был бы рад прочитать расширенную версию.
      • НЛО прилетело и опубликовало эту надпись здесь
          +1
          Да, macOS Sierra я тоже поставил. Традиционно перестали работать мои любимые CleanMyMac и HandsOff (Фаервол), но надеюсь в ближайшее время мне удастся их обновить.Что касается Xcode 8 beta — симуляторы работают, так же в Xcode немного изменился шрифт (особенно заметно на знаках препинания).

          Из того, что мне не понравилось (остальным возможно понравится) — в Xcode 8 переработали панель инструментов позиционирования (скрин), больше нет универсальной формы для всех девайсов — под каждый девайс отдельные настройки отступов. Кнопка «Clear Constaints» у меня перестала работать вовсе, никакой реакции, пришлось удалять «Constaints» вручную по одной из левого списка с иерархией форм. Перезагрузка не помогла. Буду разбираться.

          Но Xcode 7.3 (стабильный) у меня остался, так что нет причин переживать за невозможность собрать рабочий проект.

          image
            +3
            Привет. Тоже хочу поставить сиеру на выходных, но боюсь, что AppCode сломается, так как это моя основная среда разработки. Вы не проверяли, работает ли эта IDE нормально на новой системе? Спасибо.

            ps.
            Если кто-то поставил ios 10, то чтобы в старом xcode (7.3) можно было работать с девайсом, нужно просто из xcode 8.0 скопировать в него папку в тоже место. Сообщаю просто так, вдруг кто не знает.
            Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.0 (14A5261u)
            
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Спасибо, проверил, добавил ваше предупреждение в начало статьи
              • НЛО прилетело и опубликовало эту надпись здесь
                • НЛО прилетело и опубликовало эту надпись здесь
                0
                Среди новых команд к Siri вычитал такую «Насколько мощный мой компьютер». Попробовал… Видимо Siri видала железо помощнее моего Mac Pro :)

                image
                  +1
                  установил вчера iOS10 beta на iPhone 6 голос Siri пропал. У Вас так же? И кто знает как это исправить?
                    +1
                    Попробуй перезагрузить iPhone, вдруг поможет (лично у меня разовая перезагрузка Mac и iPhone устранила несколько UI багов)
                      +1
                      да спасибо все исправилось )
                    +1

                    Оно таки работает:
                    image

                    0
                    Насколько я понял сири сможет отправлять сообщения в тех же мессенджерах, а зачитывать она их сможет? Было бы здорово, особенно если бы она не теряла контекст
                      +2
                      Отлично! Попробую на Свифт это же сделать!
                        0
                        Я не iOS разработчик, но с интересом слежу за развитием платформы.
                        Мне, как бэкенд разработчику, предоставляемое API кажется довольно странным… Т.е. услышав анонс того что Siri открыли разработчикам, я ожидал совсем другого API (более декларативного и гибкого). А в итоге есть 5-6 ограниченных сценариев и привкус разочарования. Может просто я привык к тому что API должно покрывать как частные случаи, так и позволять более гибко работать с обобщенным сценарием.
                        Какого ваше (iOS разработчиков) мнение насчет предоставленного API? Как много реальных use case-ов оно покрывает?
                          +1
                          Я ждал, что API Siri позволит распознавать любую речь внутри моего приложения, но получил возможность вставить кусочек моего приложения в Siri. На данный момент я пользуюсь только двумя сценариями Siri, которые выглядят примерно так:

                          • Установи будильник на 7 утра
                          • Напомни о конференции в четверг в 15-30

                          Новое API добавляет с моей точки зрения только один полезный use case — «Вызови UBER/Яндекс.такси», и думаю именно для этих компаний оно и полезно.

                          Не думаю, что кто-то будет активно пользоваться «Siri, отправить деньги», ведь это может быть и так:
                          — Siri, отправь триста долларов моему брату
                          — Окей, я отправляю три тысячи сто долларов в Apple.

                            0
                            Примерно того же ожидал и я.
                            Я думал что можно будет декларативно описать какой контекст вызывает мое приложение и какие команды в нем доступны.
                            Например в моем приложении можно управлять роботом. Я ожидал что можно будет попросить Siri «передай Дэниелю <расследуй преступление>». А так максимум что я могу его попросить, это поставить будильник…
                            Для меня это API пока на уровне «все равно лучше, чем ничего». Я понимаю что они взяли пару популярных use case-ов и позволили их запускать через Siri, но если они таким образом делают основу, то боюсь API нормального развития не получит.

                            Нужно посмотреть как это организованно в Amazon Echo. Быстрый поиск показал что Google Now позволяет похожим образом вызывать пару частных команд (по крайней мере сейчас).

                          0
                          Там же можно добавить фразы в vocabulary

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

                          Самое читаемое