На Хабре уже были статьи про TestFlight (вот тут и тут), но в них речь шла главным образом про его использование и интеграцию/автоматизацию в процесс сборки. А мне всегда было интересно, как это работает изнутри:
• Как происходит сбор идентификаторов устройств? (Если вам непонятно, зачем собирать UDID’ы, пройдите по ссылкам выше)
• Как приложение устанавливается по переходу по ссылке?
• Как создается иконка на Home Screen?
• Все это хаки или легальные способы?
Если вы хотите построить свой TestFlight c блэк-джеком и всем остальным или просто интересуетесь, как сделано что-то из вышеперечисленного, – прошу под кат.
Предполагается, что читатель уже знаком с сервисом TestFlight и болью iOS-разработчиков – необходимостью собирать идентификаторы iOS-устройств. Testflight позволяет получить UDID очень просто – установкой Configuration Profile.
Профайл – это обыкновенный xml-файл, который благодаря разрешению “.mobileconfig” и оговоренному в документации Apple формату обрабатывается как руководство к действию, то есть интерпретируется операционной системой как описание настроек, которые нужно применить. Основное предназначение технологии – автоматическая настройка большого количества iOS-устройств, используется в основном в корпоративной среде.
Configuration Profile может содержать различные блоки, которые называются Payloads; каждый блок – это некая функциональность. С помощью Configuration Profile можно:
• Устанавливать политики запароливания
• Запретить использование устройств или сервисов
• Настроить сеть, VPN-доступ
• Настроить IMAP, Exchange, LDAP, CalDAV-аккаунты
• Создать иконки на Home Screen
• Установить сертификаты
Но как это все поможет получить UDID?
Существует специальный payload, который не устанавливает никакие настройки. Он называется Profile Service Payload и используется в многоступенчатом процессе включения iOS-устройств в корпоративные ряды (Over-The-Air Enrollment and Configuration). Для построения такой системы в полном объеме необходим сервер с поддержкой Simple
Certificate Enrollment Protocol (SCEP) – у Testflight и аналогичных сервисов используется именно такой. Для поддержки SCEP протокола существуют платные (от Microsoft) и бесплатные open source-решения, например OpenSCEP.
Но, как оказалось, существует и более простой способ получения UDID устройства – реализовать только первый шаг из всего процесса принятия устройства в корпоративную среду. Этим шагом является запрос информации с устройства, так можно получить UDID, IMEI, ICCID, MAC адрес устройства, модель (например, iPad3,1 или iPhone4,1) и версию iOS. Для реализации только этого первого шага вполне достаточно обычного web-сервера.
Итак, ваш configuration profile может выглядеть примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<dict>
<key>URL</key>
<string>http://SERVER_URL/enroll.php</string>
<key>DeviceAttributes</key>
<array>
<string>UDID</string>
<string>IMEI</string>
<string>VERSION</string>
<string>PRODUCT</string>
</array>
</dict>
<key>PayloadOrganization</key>
<string>parallels.com</string>
<key>PayloadDisplayName</key>
<string>Profile Service</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
...
При установке его пользователем информация об устройстве
будет отправлена по указанному SERVER_URL методом POST. Если вы реализовываете взаимодействие по протоколу SCEP, а на присланную информацию нужно ответить
специальным SCEP Payload. Подробнее об этом можно почитать в документации Apple. Последним шагом в обмене профайлами и сертификами в случае с Testflight будет Configuration Profile с Web clips payload, благодаря которому на Home Screen iOS устройства появится ссылка на сервис.
И это, вообще говоря, единственный программный способ создания иконки на рабочем столе.
В случае, если вы имеете дело с корпоративной инфраструктурой, в последнюю очередь на устройство присылается configuration profile со всеми настройками. Этот профайл устанавливается сам, без каких-либо дополнительных вопросов пользователю.
Если ваш путь – не реализовывать SCEP на сервере, то отвечать на полученную информацию с устройства не обязательно. Правда нужно иметь в виду, пользователь после установки профайла получит неприятное сообщение:
Такого развития событий можно избежать, установив в вашем скрипте-обработчике redirect, как подсказывают в одной из веток на форуме разработчиков Apple. И вот тут получение идентификационной информации с iOS устройств в общем-то можно считать законченным.
Теперь разберемся, как TestFlight устанавливает приложения.
Такое “письмо счастья” получает каждый ваш тестер после сборки новой версии приложения:
Кнопка Install вызывает переход по ссылке вида:
itms-services://?action=download-manifest&url=http://url/app-manifest.plist
• “itms-services” означает использование Custom URL Scheme – технологии, которая позволяет приложениям взаимодействовать – вызывать одно из другого с передачей параметров запуска. Какое приложение обрабатывает именно такие ссылки непонятно, про похожие ссылки известно: “itms” – обрабатывается iTunes, “itms-books” – iBooks, “itms-apps” – App Store. С большой вероятностью, это специальное системное приложение, которое отвечает за установку приложений. Но не только системные приложения могут иметь custom URL, любое приложение может зарегистрировать свой собственный, указав его в Info.plist. Узнать URL интересного вам приложения и сообщить URL своего приложения общественности можно через специальный сервис handleopenurl.com.
• “url=http://url/app-manifest.plist” указывает на манифест, который хранит минимальный набор данных о приложении: название, категория и указания, где скачать бинарник приложения и его иконку. Такой манифест может сделать с помощью Xcode, если выбрать тип распространения “enterprise”.
• “action=download-manifest” – действие, которое должно быть выполнено вызванным приложением и, очевидно, означающее, что манифест описанный выше нужно скачать.
Как вы можете видеть, особых сложностей в реализации системы, подобной Testflight, нет, но мы в Parallels продолжаем использовать это готовое решение, так как серьезных причин для реализации внутреннего сервиса пока не видим.
Статья подготовлена по мотивам выступления на Yandex Mobile Camp Spb.
Автор: master1981