Достаточно плотно разработкой программного обеспечения для часов я занимаюсь с 2017 года. За этот период сменилось 4 версии WatchOS (5, 6, 7, 8). Появилось больше функционала и исправлено множество баг с внедрением каждой новой версии Swift и WatchOS. UI, Complications, Bluetooth на часах эволюционировали, получая при этом более полноценные возможности работы.
За 5 лет работы в сфере разработки приложений для часов мне пришлось столкнуться с множеством различных проблем и задач. Я хотел бы поделиться опытом и получить критические замечания относительно проделанной работы. Заранее сделаю оговорку, что решения, используемые в моей разработке, не претендуют на истинно верные. Не буду спорить, что что-то можно было бы сделать по-другому и лучше.
UI
До версии WatchOS 6.0 Разработка UI на часах была основана на инструментах Interface Builder в storyboards. Отсутствие autolayout, как на iOS, компенсировалось наличием Groups и insets в Interface Builder для watchOS. Программную разработку UI внедрили с появлением SwiftUI, на который постепенно приходится переводить все приложение, так как новые фичи появляются именно там. Видимо, таким образом apple принуждает переходить на Swift UI.
На мой взгляд, было бы разумнее делать сложную анимацию для часов на Sprite/Scene kit. Это, конечно, увеличивает время на саму разработку, но, в то же время, уменьшает размер приложения. Тем не менее, для ускорения процесса разработки мною применялся просто набор картинок кадров (предварительно подготовленных дизайнером и сжатых до минимального размера), из которых получался необходимый видеоряд. Когда анимация не слишком сложная, можно все нарисовать в Core Animation. Например, когда нужно имплементировать графики. В дальнейшем, сложную анимацию я переведу на Scene kit. Это позволит уменьшить размер приложения и сделает процесс анимации более гибким и управляемым. Картинки и ручное рисование - это всегда tradeoff. Если грамотно их ужать (убрать избыточность), то размер даже длительной анимации не превысит пары мегабайт. Даже для часов это не так уж и критично. Также стоит отметить, что не факт, что рисование программными средствами всегда даст больший прирост в производительности и размере приложения, чем отрисованная картинка. Это индивидуальный вопрос для каждой задачи.
Касаемо работы с дизайном c Figma, при запуске на реальном устройстве обрезало часто элементы управления снизу из-за bezel (ободок). Чтобы этого избежать, необходимо делать отступы и проверять функционирование на всех размерах часов.
К сожалению, на симуляторе apple watch UI выглядит немного иначе, чем на реальных устройствах (не говоря о различных поколениях). В добавок к этому, на 8 watchOS высота top bar иная, чем на версиях ниже, и нужно адаптировать UI так, чтобы вcе элементы были в видимой части экрана. В моем случае приходилось иметь хотя бы одно устройство из каждой серии часов разного размера.
Одной из особенностей работы часов является работа энергосберегающего режима. Если ваше приложение требует длительного взаимодействия с активным экраном, то это явно не вписывается в концепцию apple по энергоэффективности, и вам необходимо найти другие способы для решения этой проблемы. Помимо включения в настройках wake up до 70 секунд, необходимо имплементировать Always-on display dimmed state в watchOS 8 TimelineView функционал обновление экрана. TimelineView функционирует только на SwiftUI.
Pixel hunting всегда имел место и не был самым приятным занятием, несмотря на меньшее количество элементов на экране. Осложняется также как на телефоне различными размерами экранов часов.
Дизайн UI на часах отличается от дизайна элементов управления для телефонов. UI разрабатывался как небольшое портативное устройство. В свою очередь, большинство пользователей не обладает абсолютным зрением и настолько хорошей координацией, чтобы попасть пальцем в маленькую кнопку, особенно когда человек находится на пробежке и глаза слезятся. Однако, убедить дизайнера, что маленький экран размером 38 подходит для комфорного использования далеко не всем (мелкие детали – такие, как графики и надписи) не всегда венчалась успехом.
Интересным пользовательским опытом оказалось использование haptic часов для индикации процесса получения данных с периферийного устройства и индикации старта и начала получения данных. Как в случае, когда экран на часах гас частота замера мог погаснуть так как данные шли медленнее в background. Но, тем не менее, конец замера можно было легко идентифицировать с окончанием пульсации и финальной вибрации. Следует отметить, что механизм haptic следует внедрять с пристальным вниманием, поскольку у некоторых пользователей он вызывал раздражение, и многие его идентифицировали с биением собственного сердца, что, в свою очередь, создавало комичные ситуации в некоторых случаях.
Complications
Complications отображают актуальную информацию приложения на циферблате, а также позволяют запускать приложения непосредственно с циферблата часов.
Можно настраивать циферблат вручную или применять готовый набор watchface для отображения данных, генерируемых приложением на циферблате. Complications позволяют отображать текст и картинки в зависимости от их типа. C данным функционалом особых проблем не возникло. Если не брать во внимание тот факт, что иконки должны быть подготовлены правильно в соответствии с инструкцией (использовать только альфа канал) и правильно поправить info.plist. Также нужно отметить, что, начиная с версии часов 7, можно расширить семейство Complications. А начиная с версии 8, появилась возможность обновлять данные Complications, когда основное приложение находится в фоне. Данная фича может пригодиться в том случае, если необходимо быстро запустить приложение с циферблата и всегда видеть актуальную информацию приложения. Начиная с версии WatchOS 7 появилась возможность добавять дескрипторы что позволяет иметь подтипы Complications. А начиная с WatchOS 8 появилась возможность обновлять данные complications, когда приложение находится в background и получает данные от переферийного устройства по Bluetooth.
Watch Face
Watch face представляет из себя набор Complications вашего приложения, который можно поделиться между другими пользователями, начиная с версии watchOS 7 и выше. Однако, следует помнить, что не все watchface доступны на всех сериях часов. Например, Nike и Hermès доступны только для соответствующих серий часов.
Из-за имплементации этой фичи apple изменила url scheme для часов itms-watchs://, что нарушило переход в watch app и показ алерта: "Watch Face Unavailable" "This watch face is not available with your current version of watchOS". Все-таки методом проб и ошибок выход был найден, но отсутствие соответствующей документации сильно замедлило процесc поиска решения.
Фича очень способствует брэндированию приложения на часах и помогает юзеру собрать complications в готовый набор, вроде дашборда с актуальными данными.
HealthKit
С течением времени так сложилось, что мне, в основном, приходилось разрабатывать функционал для отслеживания физического состояния пользователя. В медицинских и спортивных целях. Это, в свою очередь, требовало полной интеграции приложения с функционалом Health Kit, записи и чтения активности пользователя. Однако, еще одной интересной особенностью библиотеки HK является возможность запуска workout. Данная функция одновременно запускает приложение на часах, то есть, делает его активным. В некоторых use cases использования часов было очень удобно, когда пользователь запускает приложение на телефоне, и автоматически запускается приложение на часах.
В новой версии HealtKit позволяет читать данные когда приложение находится в фоне. Эта особбеность очень помогает, когда нужно взаимодействие с переферией часов и обменом данных активности пользователя.
Motion detection
Еще одним способом записи активности пользователя является получение данных с гироскопа и акселерометра часов. Примение этих данных достаточно широкое. От состояния здоровья пользователя до его физической активности в течении всего времени использования часов. На часах гироскоп работает несколько иначе, чем на телефоне. В WatchOS есть специальное API для получения данных с гироскопа. Тем не менее, данные можно получить только из числового массива для акселерометра.
Для обеспечения непрерывности потока данных в критических случаях разрыва соединения между телефоном и часами нам пришлось организовывать досылку данных при восстановлении соединения. К тому же, получение данных с акселерометра часов сопровождается различными проблемными случаями: тут и блокировка телефона, и телефон на зарядке, и низкий заряд батареи. Для борьбы с каждой проблемой был имплементирован механизм, позволяющий фильтровать поток данных из базы данных и запрашивать только те участки, в которых содержались данные от сенсоров.
Data Synchronization
Обмен данными между iOS и watchOS возможен следующими способами:
Обновление контекста приложения
Отправка сообщений
Передача пользовательской информации
Передача файлов
Обновление Complications через приложение iOS
От себя добавлю, что на часах возможен обмен данными через http, но это довольно неординарный способ.
Apple рекомендует использовать для обмена данными отправку сообщений. Я бы полностью с ними согласился. Но на ранних версиях watchOS были проблемы с работой в background, и я был вынужден переключиться на использование передачи пользовательской информации (через userInfo). Однако, способ передачи пользовательской информации не работает на симуляторе и не имеет механизма подтверждения доставки сообщения, что требует доработки этого механизма: добавления функционала подтверждения доставки отправленной информации.
Так как данные передаются по радиоканалу и вероятность ошибочной передачи выше, чем у проводного соединения, и учитывая, что данные отправляются последовательно, обмен информации может занять достаточно много времени – до нескольких секунд. Поэтому при проектировании, рекомендую максимальную часть расчетов и обработки производить на часах, сжимать передаваемую информацию. В таком случае можно минимизировать временной процесс обмена информацией при передаче неоднородных данных.
BLE
Обмен данных по каналу BLE между часами и периферийными устройствами возможен только в том случае, когда часы работают как BLE Сentral устройство. Возможно, в следующих версиях часов (watchOS) добавят работу как Peripheral, но мне пока не удалось запустить часы как периферийное устройство. До версии watchOS 8 при переходе в background приложения или когда экран гас соединение, передача данных с периферийными устройствами прерывалась, приходилось всевозможными способами заставлять работать BLE в background. В моем случае, запускался workout, который гарантировал работу BLE устройства более-менее стабильно в режиме background. Тем не менее, режим workout сильно расходует батарейку часов (включаются все датчики: от датчика пульса до акселерометра и гироскопа). Поэтому его нужно использовать, когда происходит критическая передача данных между часами и периферией, и обязательно отключить, когда она закончится. Необходимо помнить, что при ревью вашего приложения, apple очень ревностно относится к энергосбережению и требует объяснения причины включения workouts. К счастью, в моем случае, включение workouts всегда можно объяснить необходимостью получения данных с датчиков часов вместе с данными от периферийного устройства, так как пользователь, например, выполнял тренировку.
Тем не менее, в watchos 8, наконец-то, включили поддержку работы BLE в background . Это позволит отказаться от множества сложностей при разработке подобных приложений.
OTA DFU
OTA DFU (Updating firmware over the air) обновление встроенного програмного обеспечения по воздуху. В данном случае иеется ввиду обновление firmware с использованием BLE на переферийном устройстве через часы.
В периферийном устройстве (в проектах в которых учавствовал) в качестве электронных компонентов для портативных устройств выступали чипы компании Nordic. Так как обновление планировалось делать на часах, а библиотека была рассчитана только для iOS устройств – пришлось стать контрибьютором для iOS DFU Library чтобы и для apple watch ее тоже можно было бы использовать. Пока сам процесс обновления приходится запускать через включенный workout, потому что библиотека еще не адаптирована (на момент написания статьи) для работы в background. Для того, чтобы без лишних затруднений провести обновление и не сломать периферийное устройство (не окирпичить -- не сломать), очень рекомендую использовать отладочные платы Nordic. Плата отладочная Nordic очень удобна, когда физически отсутствуют BLE устройства для которых разрабатывается програмный продукт. В действительности, приходится обращаться с просьбой адаптировать прошивку для отладочной платы. Но это очень незначительное неудобство, которое мы претерпеваем за возможность эмулировать физические подключения и обновления прошивок без риска повредить устройство. Использование такой электронной платы позволяет, не дожидаясь выхода опытного образца, начать разработку программного обеспечения для BLE устройств. Я пользуюсь ей на нескольких проектах, и она достаточно серьезно помогла избежать множества проблем, так как может эмулировать любое BLE устройство, собранное на чипсете Nordic.
Audio
Сложности в обработке звукового сигнала возникали в основном из-за неполноценного API получения звукого сигнала. Некоторые библиотеки ообработки были доступны начиная только с версии 6.1 watchOS.
Для разработки и обработки цифровых сигналов лучше применять библиотеку vdsp, что существенно снижает нагрузку на процессор и увеличивает скорость обработки вычислений. Однако, при отладке приложения в debug на часах третьей серии на watchos 6.0 я столкнулся со странной особенностью. Часы в дебаге режиме работали практически на два порядка медленнее, чем часы, например, 4 серии. Мы уже начали повышать требования к минимальной версии часов для приложения, пока не обнаружили, что в релизной сборке проблем со скоростью обработки звука практически не было. Оказалось, что до 4 версии часов компилятор не способен адекватно оптимизировать сборку приложения, в котором используются много вычислений с плавающей точкой. Другой особенностью работы со звуком является его настройка в функции setCategory(_:mode:options:). По логике, если вы занимаетесь обработкой звука, то mode: на выставить в measurement . Однако, в этом режиме так и не удалось провести анализ звука, который использовался для передачи данных. Режим default, как оказалось, подходит для этого как нельзя лучше.
Так же обнаружилось, что при инициализации приложения в момент запуска, например, c циферблата через complications, приложение начинало инициализировать настройки микрофона, и по какой-то причине устанавливало нулевую частоту звука. Обратившись в TSI после долгой переписки, представитель Apple признал, что это баг и попросил завести его в системе. Тем не менее, проблема до сих пор не решена.
Еще одним важным замечанием при работе со звуком на часах было периодическое зависание функции callback func installTap(onBus bus: AVAudioNodeBus, bufferSize: AVAudioFrameCount, format: AVAudioFormat?, block tapBlock: @escaping AVAudioNodeTapBlock). При длительной работе микрофона данная функция могла перестать отрбатывть передачу данных. Решением было вызов func reset() в AVAudioEngine если данные перестали приходить по timeouts.
Permissions
Разрешение на использование определенных функций, например, микрофона или BLE, можно давать как на iOS устройстве, так и на часах. Однако, если принять разрешение на часах при запущенном на телефоне приложении, то на телефоне оно получит сигнал terminated и покрешится и, наоборот. Сделано это, возможно, в целях безопасности для того, чтобы измененные разрешения корректно синхронизировались между операционной системой и приложением. Любой краш: либо на телефоне, либо на часах, не является приемлимым. Поэтому обычная стратегия запрашивать разрешения на телефоне в таких случаях пока находится в приложении на часах.
Tests
Начиная с 13 версии Xcode, стало возможным имплементировать UI/Unit tests для Watch OS. Это стало очень актуальной фичей в особенности, когда кодовая база приложения для часов достаточно большая, и есть много критичных участков приложения, необходимых для покрытия тестами. Однако, пока фича работает не особо стабильно – Xcode падает при попытке их запуска на моем проекте. Возможно, в следующих версиях Xcode ситуация изменится.
Debug
Встроенный debagger на часах позволяет запускать стандартный отладчик. Но так как взаимодействие идет по радиоканалу, то отладка работает крайне нестабильно. Не говоря о том, что она довольно долго запускается на реальных устройствах. Поэтому лучше использовать разработку на симуляторе, а на реальных устройствах добавить логгер, например, CocoaLumberjack. Или можно установить профиль и получать логи в приложении Console. Лично в моем случае, дебаггер для часов не всегда адекватно запускался и работал нестабильно, и требовалось перезапускать и переподключать устройства iOS и watchOS и Xcode.
Для удобства разработки и тестирования UI на симуляторе необходима разработка эмулятора переферийного BLE устройства. Это применимо и актуально не только для часов, но также для разработки переферии для телефонов и планшетов. Что касается CoreBluetooth, то swizzling позволяет полностью эмулировать работу BLE устройств подменяя реализс помощью стабов, подобно стабам для сетевых запросов.
Conclusion
Эволюция железа и софта для apple watch прошла долгий путь от простого клиента до полнофункционального и независимого в эксплуатации устройства. Разработка для портативных устройств идет тем же путем, как и для телефонов, планшетов и полноценных компьютеров. Создание продуктов для apple watch постепенно становится сложнее и разнообразнее. Несмотря на некоторые различия в работе функционала на watchOS по сравнению с ios, подход становится универсальным, работа с UI – единой, благодаря использованию Swift UI.
Возможность часами обрабатывать звук и подключаться по BLE, как в случае с телефоном, делает часы независимым от телефона устройством и позволяет создавать приложения, работающие только на часах, начиная с версии watchOS 6.
Разработка на часах пока не столь популярна из-за не столь распространенного их использования и слабой элементной базы, но очень перспективна и, наверняка, будет
востребована в будущем наряду c разработкой для телефононов. Компания Apple активно развивает HealthKit, CareKit, ResearchKit, добавляя все больше функций и возможностей в него. Поэтому есть предположения и перспектива, что баги будут исправляться и многие ограничения, например для BLE, будут сняты.
Комментарии (6)
v1000
16.05.2022 00:07Раз уж тема про здоровье, как на счет излучения от самих часов?
Понятно, что сама методика изменения довольно запутанная, но даже если отталкиваться от конкретных значений в https://www.apple.com/legal/rfexposure/
Все-таки это устройство, постоянно носимое на руке, и довольно плотно к ней прилегающее. Опять же, технологии отслеживания сна, когда часы надо держать надетыми на руку всю ночь.
Вроде как мощность излучения должна зависеть от мощности устройства, но при этом у 7 модели излучение на кисть заявлена 0.03, а у SE, которые вроде менее мощные, 0.20.
Есть-ли вообще какие-то ограничения при разработке программ для часов, ведь, как понимаю, излучение так-же зависит от нагрузки на процессор и использования беспроводный интерфейсов?
evgzor Автор
16.05.2022 10:18+1Спасибо за интересный вопрос. Что касается SE то это аналог Apple Watch Series 4 (насколько мне известно - очень похожа элементная база хотя могу ошибаться) 7 ая серия стала намного энергоэфективнее. Одно из ограничений это энергоэфективность. Приложение не должно высаживать батарею и существенно сокращать время работы. Не важно чем занимается приложение: коммуникация с переферией, длительный расчет или оставлять не включенным workout. Долгое использование процессора например при пересчете данных акселерометра может привести к удалению из памяти приложения, когда оно например находится в background. Каких то конкретных цифр, к сожалению, привести не могу так как в своих проектах мы просто ставили паузу на расчет, чтобы приложение оставалось рабочим в течении всего времени пока часы были включены. По поводу переферии, то часы, когда уходят в background и гаснут существенно снижают частоту опроса и с учетом того, что это BLE устройство, не значительно просаживают батарею. Что касается разработки переферии то есть определенные требования https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf которым надо следовать.
NSA-bot
Спасибо за статью. Появились направления для дополнительного чтения. Подскажите, а в SwiftUI для часов возможно программное добавление элементов интерфейса и изменение их размеров и т.п.?
evgzor Автор
Да, конечно. Размеры, позиции все есть. Единственно UIKit (изначально) не доступен, а так ограничений по сравнению c iOS не нашел. Хотя справедливости ради, пока только несколько экранов перевел. Возможно какой то функционал еще не успел затронуть с которым есть трудности.
NSA-bot
У меня программирование - хобби :) И я с очень вялой скоростью делаю беговое приложение. Сначала я решил сделать только самые основные экраны, старт, обратный отсчет, экран с метриками + экран с паузой и завершением, экран с итоговыми данными пробежки и опять на стартовый. Со SwiftUI у меня плохо, но насмотревшись видео про спортприложение для часов с WWDC2021 (возможно вы его видели), решил попробовать. Сначала получалось, но в итоге я перешел на WatchKit, так как не смог победить некоторые проблемы. Прикрутил ко всему этому HKWorkout, Motion и Location по минимуму, чтобы убедиться, что всё работает. Всё заработало. Теперь хочу сделать экраны метрик с разным количеством полей и вот тут я опять вспомнил как хорош программный интерфейс на айфоне. А тут получается надо делать отдельные экраны, с классом для каждого. Предполагаю, что придётся всё таки осваивать SwiftUI, так как, как я понял в том числе и из вашей статьи программно количество полей не поменять в простом WatchKit :(
evgzor Автор
SwiftUI в любом случае надо учить - за ним будущее на мой субьективный взгляд. Много ограничений снимает (при разработке на часах UI) и его скорее всего будет продвигать Apple как единый способ разработки UI на всех платформах (iOS, watchOS, tvOS). Новые функции (UI) например сейчас только там появляются. Пока что еще полностью от Storyboards не ушли, но вектор развития понятен.