- Сервисы дистрибуции мобильных приложений для iOS. Часть 1: TestFlight
- TestFlight от Apple
- Регистрация и интеграция
- Основной функционал
- Дополнительный функционал
- Continuous Integration
- Apple Wallet. Что это такое и как интегрировать в него свою карту
- Структура карты
- Посадочный билет
- Купон
- Билет на событие
- Общая карта
- Скидочная карта
- Структура pass.json
- Обязательные поля
- Ключи для связанных приложений
- Ключи стиля
- Ключи визуального оформления
- Баркод
- Локация
- Оборотная сторона
- Создание карты. Часть 2
- Интеграция с приложением
- Добавление карты
- Получение информации о добавленных картах
- Проверка на уникальность
- Тестирование
- Заключение
- Используемые материалы:
Сервисы дистрибуции мобильных приложений для iOS. Часть 1: TestFlight
С каждым годом становится всё очевиднее, что для распространения тестовых версий iOS-приложений нужны специализированные сервисы. Это актуально не только для компаний, занимающихся разработкой приложений в “промышленных масштабах”, но и для инди-разработчиков. Причины: увеличение количества устройств с “нестандартным”/”не кратным” размером экрана, отличия в архитектуре центрального и графических процессоров — всё то, что раньше было повседневностью для разработки под Android, теперь становится справедливым и для iOS.
Исторически самым популярным сервисом дистрибуции являлся TestFlight — практически идеал, как в техническом отношении, так и в юзабилити. Однако, после приобретения компанией Apple в начале 2014 года, сервис претерпел ряд неоднозначных изменений, которые с одной стороны сказались негативно на его позиции лидера, а с другой дали шанс альтернативным сервисам побороться за первое место и предложить как минимум равноценную замену, а может быть и что-то более удобное и функциональное.
В своей серии статей я собираюсь поделиться результатами сравнения нескольких сервисов дистрибуции и в результате помочь другим, кто стоит перед таким же вопросом выбора.
В обзоре участвуют следующие сервисы (в таком порядке и будут публиковаться части обзора):
- Apple TestFlight
- HockeyApp
- Ubertesters
- Crashlytics (как часть Fabric)
TestFlight старой версии не будет рассмотрен, так как хотя он по-прежнему работает и доступен по адресу www.testflightapp.com, использование его в долгосрочной перспективе не имеет смысла по ряду причин:
- нет никаких гарантий, что Apple не приостановит или не прекратит его работу в любой момент
- SDK сервиса не доступно для скачивания, более того невозможно использовать сервис, если приложение использует SDK
- сервис больше не является кросс-платформенным, поддерживается только распространения приложений для iOS (подробнее)
Важно! Буквально накануне публикации статьи команда TestFlight (старой версии) разослала уведомление, в котором сообщается, что старый сервис прекратит свою работу 26 февраля 2015 года (подробности).
Система оценки: сервисы будут оценены по 10-балльной шкале по каждому из разделов (Регистрация и интеграция, Основной функционал, Дополнительный функционал, Continuous Integration). Суммарная оценка позволит определить победителя (итоговое заключение войдет в последнюю часть обзора).
TestFlight от Apple
Регистрация и интеграция
Для использования сервиса кроме аккаунта разработчика (iOS Developer Program) необходимо получить доступ к iTunesConnect. Функционал зависит от роли (группы), к которой относится используемый аккаунт iTunesConnect. Пользователи из группы Technical могут:
- включать/отключать режим TestFlight Beta Testing для приложений (вкладка Prerelease)
- выбирать тестеров из списка доступных Internal Testers, но не имеют возможности формировать этот список на странице iTunes Connect -> Users and Roles -> TestFlight Beta Testers -> Internal
- формировать список внешних тестеров My Apps -> APP -> Prerelease -> External Testers (но для распространения версий для внешних тестеров приложение должно пройти ревью в Apple)
Пользователи из группы Admin обладают теми же правами, что и пользователи группы Technical, а также могут добавлять новых пользователей в список Internal Testers.
На данный момент установка или использование какого-либо специализированного SDK не требуется.
Основной функционал
Если сравнивать новую версию TestFlight с тем, что было доступно разработчикам ранее в рамках стандартных сервисов Apple, то она, в чем-то, несомненно, является шагом вперед. Так, например, количество тестеров увеличено с условных 100 до 1125 (из которых 100 — это доступные и раньше устройства для AdHoc распространения, 25 — это внутренние тестировщики (Internal Testers), а 1000 — внешние (External Testers)), причем если ранее привязка осуществлялась к устройству, то теперь уникальным идентификатором является Apple ID, а значит каждый тестер может проверить работу приложения на всех доступных ему (и, конечно, поддерживаемых приложением) устройствах.
Примечание (от 15 июня 2015): количество устройств, доступных при использовании AdHoc provision profiles с с 8 июня 2015 года было изменено со 100 суммарно, на 100 на каждое семейство устройств (изменение произошло после объявления на WWDC об объединении всех developers programs в одну).
Разница между внутренними и внешними тестировщиками заключается в дополнительном шаге, который добавляется во втором случае: тестовая версия приложения должна быть отправлена для обзора и одобрена специалистами Apple (Beta App Review). Причем первоначальный обзор будет проводиться более тщательно, а все последнующие могут проходить быстрее (но не обязательно). Это, конечно, накладывает определенные ограничения на процесс разработки и требует дополнительного планирования фаз тестирования приложения, с учетом неопределенности сроков прохождения обзора (как и в случае с обычным обзором приложений перед публикацие в AppStore, при отказе в публикации, повторная заявка рассматривается снова в порядке очереди).
Но есть другие особенности, которые отличают решение Apple от альтернативных, увы, не в лучшую сторону:
- Приложение-клиент сервиса может быть установлен только на iOS 8.0 и выше, соответственно нет возможности тестировать приложения на устройствах с iOS предыдущих версий.
- Для распространения тестовых версий необходимо создать AppStore Distribution provisioning profile и настроить профиль приложения в iTunes Connect.
- Так как загрузка дистрибутива приложения осуществляется через стандартный визард Xcode -> Archive -> Export, необходимо чтобы проект приложения содержал 3 основных иконки.
- Количество приложений, одновременно доступных для тестирование ограничено 10.
- Сервис работает очень медленно, это касается как скорости обновления списка доступных приложений и их версий, так и скорости скачивания/установки приложений на тестовые устройства.
- Отправка отзыва с тестового устройства осуществляется при помощи приложения-клиента, но так как это обычное письмо, нет возможности прикрепить скриншот (как плюс можно отметить, то что в письмо автоматически вставляется блок с описанием характеристик тестового устройства).
- Возможность отправки отзыва появляется только, если в iTunes Connect в настройках версии имеется указание, что именно требуется протестировать (а если не будет указан адрес электронной почты для получения отзывов, то поле “To” в письме окажется незаполненным).
- Для тестирования может быть доступна только одна версия приложения (тестер не имеет возможность для выбора, настройки доступности делаются в профиле приложения в iTunesConnect).
- Поле “Feedback Email” в настройках версии приложения в iTunesConnect приходится заполнять каждый раз (логичней было бы запоминать, оставляя возможность для редактирования).
- Как не удивительно, но TestFlight в версии от Apple не является сервисом, работающим по принципу 24х7, например в конце декабря при попытке входа в iTunesConnect можно было увидеть такое сообщение: iTunes Connect is unavailable until December 29. (справедливости ради, стоит отметить, что подобные “каникулы” Apple устраивает ежегодно и рассылает уведомление за неделю до их наступления).
Однако есть и некоторые уникальные возможности: так, например, клиент сервиса (приложение TestFlight) единственный, кто наверняка знает статус установки тестовой версии, альтернативные решения попросту не имеют возможности использовать системные функцие, позволяющие реализовать подобное.
Примечание: статус установки — смена индикации процесса установки, привычная пользователям AppStore. Когда поочередно статус меняется Get — Install — Installing — Open. В других сервисах дистрибуции эта цепочка выглядит так: Install — Installing — Install — приложения попросту не знают результат, был ли установлен тестовый дистрибутив или нет. В случае же с Apple TestFlight цепочка имеет привычный вид: Install — Installing — Open.
Иконка обновленного приложения TestFlight (правильнее будет сказать, что это абсолютно новое native приложение, разработанное в Apple). Ниже пример иконки тестовой версии приложения — оранжевая “точка” позволяет определить, что это не версия из AppStore.
“Страховка” Apple от обвинений в распространении спама.
Apple не разрешает загрузку дистрибутивов без изменения версии или номера сборки.
Достаточно лаконичная и понятная страница администрирования версий приложения для тестирования.
Письмо-приглашение для участия в тестировании, HTML-форматирование не слишком оптимизировано для мобильных платформ (справедливости ради, хочу отметить, что приложение Mail отображает такие письма корректно, но письма от других сервисов отображаются нормально и в OWA).
Приложение TestFlight: информация о доступном для тестирования приложении.
Приложение TestFlight единственное умеет определять результат установки тестовой версии (кнопка Install поменялась на Open) — преимущество, полученное с переходом к Apple.
Письмо с отправленным из приложения TestFlight отзывом. Кроме скудного форматирования и невозможности добавить вложения, можно отметить еще один недостаток: отправленные отзывы попадают только в почтовый ящик, в iTunes Connect эта информация не сохраняется и недоступна.
Резюмируя, можно сказать, что обновленная версия TestFlight просто работает. В данный момент она не имеет особых конкурентных преимуществ (речь идёт о функционале, а не неоспоримом преимуществе — принадлежности компании Apple, которое пока в большей мере является потенциалом).
Дополнительный функционал
На данный момент, к сожалению, компания Apple берет только числом, а не умением. Из явного преимущества можно отметить разве что гораздо большее количество бета-тестеров, которое можно задействовать для внешнего тестирования: на порядок больше, чем у всех остальных альтернативных решений (причина ясна: компания сама контролирует условия распространения приложений и имеет преимущество перед решениями третьих сторон).
Обновление (5 мая 2015): с релизом Xcode 6.3 разработчикам стал доступен Crashes Organizer. Новый функционал, несомненно, хороший признак того, что Apple продолжает развивать свои сервисы, но, к сожалению, компания всё ещё отстаёт от других сервисов:
When you open the Crashes organizer, Xcode begins refreshing the crash reports for your apps. Xcode downloads the top crash reports—crash reports with the most number of occurrences on unique devices—that occurred during the past two weeks. However, there may be up to a three day delay between when you first distribute your app and when crash reports are available in Xcode.
Три дня задержки и период архивного доступа в две недели выглядит несколько обескураживающе.
Continuous Integration
Примечание: описанные далее нюансы использования сервисов как части непрерывной интеграции (continuous integration) в данном обзоре подразумевают, что она будет делаться на основе решения, предлагаемого компание Apple. То есть при помощи Mac OS X Server и Xcode bots — подробно на организации такой интеграции я не буду останавливаться, возможно это станет темой для отдельной статьи. Желающие могут ознакомиться с темой самостоятельно, например, обратившись к официальному руководству от Apple.
Каким бы странным это не казалось, но на данный момент не существует возможности для публикации приложений в Apple TestFlight в автоматическом режиме. Я надеюсь, что этот большой недостаток будет исправлен компанией в одном из ближайших крупных обновлений Xcode, тем более что в оригинальном TestFlight такая возможность имелась.
Итого суммарная оценка по всем разделам: 15 баллов.
Источник
Apple Wallet. Что это такое и как интегрировать в него свою карту
Принято считать, что Wallet – не самый популярный сервис в СНГ. Но уже во втором проекте подряд заказчик ставит задачу «Сделать интеграцию с Wallet». Поэтому я решил написать эту статью, чтобы рассказать о сервисе в целом и показать, как интегрировать в него свой продукт.
Что такое Wallet? Он позволяет держать в телефоне различного вида карты (билеты, скидочные карты и т.п.), облегчая жизнь пользователям продукта. Более того, есть возможность актуализировать информацию о карте посредством push-уведомлений, но это тема для отдельной статьи. Но если у вас есть карта/билет/абонемент, которые можно интегрировать в телефон, то для этого есть решение! Как это сделать – читайте ниже.
Как правило, за создание карты отвечает ваш сервер. Приложение получает карту в виде .pkpass файла и уже через приложение пользователь может добавить карту в Wallet.
Структура карты
Что же представляет собой карта с точки зрения разработчика? Карта – это архив с расширением .pkpass. Он содержит в себе все данные, необходиимые для отображения и работы карты. Содержимое архива – в таблице ниже.
Файл | Назначение |
---|---|
background.png | Фоновая картинка для карты. |
footer.png | Картинка рядом со штрихкодом |
icon.png | Иконка для уведомлений и писем |
logo.png | Логотип карточки. Отображается слева сверху |
manifest.json | Реестр всех включанымх файлов |
signature | PKCS7 подпись |
pass.json | Внешний вид и информация на карте |
strip.png | Картинка, находящаяся сзади основного описания карточки |
thumbnail.png | Дополнительная картинка (уточнить) |
Существуют следующие типы карт:
- Посадочный билет: на самолет или поезд. Обычно купон работает на одну поездку;
- Купон: для купонов и специальных предложений;
- Билет на событие: может работать как для одного события, так и для целого сезона;
- Скидочная карта: карты лояльности, скидочные или подарочные карты;
- Карта общего вида: если ничего из вышеперечисленного не подходит под ваш случай: например, карта для поездок на метро или пропуск в спортзал.
Рассмотрим схематично внешний вид разных карт. Картинки лучше называть так, как это указано в таблице выше.
Посадочный билет
Купон
Билет на событие
Общая карта
Скидочная карта
Структура pass.json
Обязательные поля. Содержат Pass Type ID, Team ID, название организации и т.п.
Ключи для связанных приложений. Нужны для отображения приложений, которые нужно «ассоциировать» с картой.
Ключи «срока годности» карточки.
Ключи актуальности. Например, координаты местности, где карта может быть использована, или начало события, для которого она предназначена.
Ключ стиля. В начале статьи были перечислены 5 видов карт для Wallet. Каждому из них соответствует свой стиль. Такой ключ должен быть строго один.
Ключи визуального оформления карты. Помимо очевидного, содержат в себе информацию о штрихкоде, отображаемом на карте.
Ключи web-сервисов. Вы можете использовать web-сервисы для взаимодействия с картой, например, автоматически ее обновлять.
NFC-ключи. Содержат дополнительную информацию для Apple Pay транзакции.
Теперь обо всем подробнее.
Обязательные поля
description | String. Локализуемое | Краткое описание карты. Локализуемое. |
formatVersion | Int | Версия формата файла. Значение должно быть 1. |
String. Локализуемое | Название организации, которая выдает карты. | |
String | Pass Type ID и кабинете разработчика. | |
String | Серийный номер отдельной карты | |
String | Team ID команды разработчика |
Ключи для связанных приложений
[Int] | Опционально. ID приложений, ассоциированных с картой. Берется всегда первое, совместимое с текущим устройством. |
String | URL, который передается в приложение при открытии |
Ключи стиля
[JSON] | Основная информация о карте. |
[JSON] | Второстепенная информация. |
[JSON] | Поля для дополнительной информации. Опциональное |
[JSON] | Заголовок карты. Отображается даже в том случае, когда карты видны списком. |
[JSON] | Основная информация о карте. |
String | Тип транспорта для карт-билетов. Может принимать следующие значения: PKTransitTypeAir, PKTransitTypeBoat, PKTransitTypeBu`, PKTransitTypeGeneric, `PKTransitTypeTrain`. |
[JSON] | Массив полей, отвечающий за обратную сторону карты |
JSON в данном случае имеет следующий вид:
Значение по ключу value может быть как числовым, так и строковым. Однако currencyCode вместе со строковым значением использовать не получится. Что касается auxiliaryFields и secondaryFields, их может быть несколько, и стоит следить за длиной строк, которые в них используются.
Ключи визуального оформления
[JSON] | Информация для баркода (см. ниже). |
color as string | Цвет фона.(#fa32e4) |
color as string | Цвет лейблов со значениями |
String | Опционально для билетов на события и билетов на транспорт. Карты с одинаковым стилем ― passTypeIdentifier и groupingIdentifier ― будут группироваться |
color as string | Текст лейблов с названиями полей |
Localizable string | Текст, отображаемый рядом с логотипом |
Баркод
Самая важная часть карты. В него зашивают идентификационный номер карты (например, номер физической карты или номер билета). Важно чтобы сканер или любой другой инструмент умели считывать коды в нужной кодировке.
String | Опциональный текст, отображаемый рядом с баркодом в том случае, если баркод не считывается. |
String | Формат баркода. Может принимать значения: PKBarcodeFormatQR, PKBarcodeFormatPDF417, PKBarcodeFormatAztec, PKBarcodeFormatCode128 |
String | Код или номер карты, зашифрованный в баркод. |
String | Кодировка сообщения. Обычно iso-8859-1 |
Локация
Эти ключи отвечают за локацию, в пределах которой карта может быть использована.
String | Опциональный текст, отображаемый рядом с баркодом в том случае, если баркод не считывается. |
Долгота | Широта |
Double | Широта |
String | Опциональный текст, который отображается на экране блокировки в тот момент, когда пользователь входит в радиус действия карты. |
Оборотная сторона
На оборотной информационной части можно разместить дополнительную информацию: условия использования, политику автообновления, контактные данные и ссылку на приложение, к которому относится карта. На рисунке представлено соответствие полей в pass.json и внешнего вида обратной стороны карты. Если в value-поле есть ссылки, номера телефона и т.п., они подсветятся автоматически.
Создание карты. Часть 2
Итак, картинки готовы, pass.json сформирован, осталось собрать все это вместе. Для этого заполним manifest.json (см. таблицу 1), куда необходимо включить все картинки и pass.json. Получается примерно так:
С этого момента менять ничего не нужно, поскольку SHA будет некорректным, в случае изменений необходимо сгенерировать SHA заново.
Далее нужно создать Pass Type ID в кабинете разработчика и сделать для него сертификат. Процедура должна быть более-менее знакомая, если ранее вы создавали, например, Provisioning профили.
Далее заходим в ключницу (Keychain) и экспортируем оттуда Apple Worldwide Developer Relation Certificate (WWDR) как .pem.
Оттуда же экспортируем созданный Pass Type ID как .p12. На этом этапе ключница попросит вас ввести пароль для сертификата. При этом пароль вводить необязательно.
Обратите внимание, что все дальнейшие действия надо производить в одной папке, где уже должны лежать manifest.json, pass.json и картинки.
Теперь необходимо сгенерировать подпись, которой будем подписывать архив. Для начала экспортируем Pass Type ID и ключ к нему как .pem.
Теперь мы готовы к генерации подписи. Сделаем это командой:
Итак, у нас все готово, осталось только собрать архив, делаем это командой:
Обращаю внимание, что тут должны быть перечислены все файлы, в которые вы хотите включить архив данных для карты(.pkpass).
В итоге мы получим .pkpass файл, который можно открывать на компьютере. Мы увидим превью карты, внешний вид которой может отличаться от вида на телефоне.
Все это можно сделать чуть проще. Apple предоставляет утилиту signpass (Apple Wallet sample meterials), которая берет на себя все подсчеты SHA (файл manifest.json можно не делать самостоятельно) и работу по созданию подписей. Чтобы ей воспользоваться, нужно собрать проект и поместить файл signpass в папку со всеми необходимыми ресурсами.
В целом структура должна выглядеть примерно так:
Далее выполняем команду:
Wallet — это название папки, в которой лежат все ресурсы. На выходе получаем файл wallet.pkpass. Его содержимое можно посмотреть, разархивировав wallet.pkpass.
Не исключено, что создание pkpass будет вынесено на бэкенд, в таком случае надо будет передать разработчикам WWDR, сертификат для Pass Type ID в виде .p12 и пароль от него.
Интеграция с приложением
Для того чтобы приложение имело возможность добавлять карты в Wallet, необходимо включить эту возможность в App ID и также включить эту возможность в Capabilities в проекте.
Это необходимо для полноценной корректной работы с Wallet. В противном случае не получится считывать карты с Wallet и, например, не будет возможности понять, добавлена наша карта или нет. Также важно отметить, что team id в pass.json должен совпадать c team id, либо придется добавлять их вручную в entitlements и это может исправить ситуацию, но это я не проверял.
Добавление карты
Добавлять карты очень просто:
Однако, опять же, чаще .pkpass файл надо будет скачивать с вашего сервера.
Стоит отметить, что PassKit выдает довольно читаемые ошибки, поэтому можно легко понять, что именно было сделано не так.
Получение информации о добавленных картах
Чтобы получить информацию о картах, имеющихся в Wallet и относящихся к вашему приложению, необходимо обратиться к объекту PKPassLibrary.
Таким образом, можно понять, добавлена карта или нет, а также обновить интерфейс. Кроме того, через PKPassLibrary карты можно обновлять и удалять. Обновлять карты можно и через веб-сервисы, но в этой статье мы не будем рассматривать такой вариант.
Проверка на уникальность
Поскольку в вашем сервисе, как правило карта привязана к аккаунту, в приложении скорее всего придется как-то определять принадлежность карты к текущему пользователю. Предлагаю делать это через serialNumber . Например, задавать в качестве serialNumber id пользователя или номер карты.
Тестирование
Apple предоставляет примеры pkpass для разных типов, можно ориентироваться на них.
Apple Wallet samples
Чтобы увидеть то, как выглядит карта, можно, добавить pkpass в проект (см. «Добавление карты»). Процесс добавления/удаления уже рассмотрен выше, осталось только напомнить, что приложение не будет видеть уже добавленные карты, если карта для Wallet создавалась на одном аккаунте разработчика, а сама разработка велась с другого аккаунта (актуально для аутсорс-компаний). При этом добавлять карты можно без проблем.
Проверить, корректно ли закодирована информация в штрихкоде, можно с помощью любого сканера QR-кодов. И точно необходимо проверить корректность работы с настоящим сканером.
Заключение
В статье был рассмотрен процесс создания и дизайна карты, а также процесс интеграции c приложением и проблем, которые могут возникнуть. Я намерено не касался вопросов интеграции с веб-сервисами и обновления карт, и надеюсь сделать это в следующей статье.
Используемые материалы:
Отдельное спасибо mehdzor за аккаунт разработчика для тестов.
Источник