Пожалуйста, опишите ошибку

Нашли баг? Помогите нам его исправить, заполнив эту форму

Как организовать в своём приложении Universal links

Команда SML

Итак, данная статья рассказывает о том, как организовать в своём приложении Universal links.

Введение

Что делать, если ваше приложение есть как на Android, так и на iOS, плюс ещё и с сервером надо что-то сделать.

Для начала давайте поймём, что это за зверь и с чем его едят. Допустим, у вас есть вебсайт. И вы хотите, чтобы пользователи мобильных устройств, нажимая на некоторую ссылку, переходили в приложение, например, в профиль пользователя. Такие ссылки и называются Universal links и позволяют всё это сделать.

В этой статье мы рассмотрим все подводные камни, которые могут встретиться у вас на пути. Начнём мы с сервера.

Сервер

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

Самый главный нюанс заключается в том, что для iOS НЕОБХОДИМО, чтобы эти ссылки вели на другой ваш домен. В противном случае, эти ссылки на iOS работать не будут.

Поэтому заведём общий домен для iOS и Android и будем настраивать его.

Настройка для Android

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

Настройка для iOS

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

Для начала необходимо создать “файл ассоциаций” с названием apple-app-site-association, который содержит в себе JSON данные о маршрутах, которые обрабатывает ваше приложение. Важный момент заключается в том, что файл не должен иметь расширение .json.

Файл apple-app-site-association должен обслуживаться под HTTPS и должен быть подписан теми же сертификатами, что сервер использует для HTTPS.

Также следует отметить, что для каждого домена файл apple-app-site-association должен быть своим.

Cоздадим файл apple-app-site-association-unsigned со следующим содержанием:

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "9JA89QQLNQ.com.apple.wwdc",
                "paths": [ "/wwdc/news/", "/videos/wwdc/2015/*"]
            },
            {
                "appID": "ABCD1234.com.apple.wwdc",
                "paths": [ "*" ]
            }
        ]
    }
}

Следует отметить, что поле "app" должно содержать пустой массив.

Поле "details" содержит ваши приложения и маршруты для привязки Universal links.

"appID" состоит из ваших team ID и bundle ID.

"paths" определяет маршруты для приложения. “*” означает любой маршрут.

Также можно исключать некоторые маршруты:

"paths": [ "/wwdc/news/", "NOT /videos/wwdc/2010/*", "/videos/wwdc/201?/*"]

Следующим шагом подписываем файл apple-app-site-association-unsigned сертификатами:

sudo openssl smime -sign -noattr \
-nodetach -in apple-app-site-association-unsigned \
-out apple-app-site-association \
-signer /path/to/public/key \
-inkey /path/to/privkey -outform DER

На выходе получаем подписанный файл apple-app-site-association.

Для проверки, что файл подписан правильно, вбиваем команду:

cat apple-app-site-association | openssl smime -verify -inform DER -noverify

Вы должны увидеть содержимое файла.

Последним шагом нам нужно указать серверу, чтобы по маршруту /apple-app-site-association он выдавал файл ваш подписанный файл.

Важно! Сервер должен выдавать файл с Content-type: application/pkcs7-mime.

В качестве сервера будем использовать nginx. Укажем настройку:

location = /apple-app-site-association {
        default_type application/pkcs7-mime;
        alias /path/to/apple-app-site-association;
}

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

Android

Для настройки простой навигации с вашего сайта на приложение Android достаточно добавить несколько строк кода в ваш AndroidManifest файл и обработку получения данных в вашем Activity.

Допустим, нам необходимо обработать переход пользователя на профиль другого пользователя в нашем приложении при нажатии ссылки на сайте. Формат ссылки будет следующим: https://google.com/user?id=2 или https://www.google.com/user?id=2. Для этого воспользуемся секцией intent-filter в нашем AndroidManifest файле.

Давайте разберемся, что и зачем нужно. android.intent.action.VIEW нужен для того, чтобы наше приложение было видимо для Google Search. android.intent.category.BROWSABLE, чтобы система смогла найти наше приложение, когда пользователь нажимает ссылку в браузере. android.intent.category.DEFAULT необходимо для того, чтобы система понимала, что наше приложение готово принимать неявные интенты.

Далее мы указываем формат ссылок, которые мы принимаем в параметре data. Система позволяет нам вводить ссылки обычного формата, это очень удобно с точки зрения web версии, так как не нужно поддерживать разные форматы ссылок. Для обработки ссылки с www и без приходится разбивать их на два разных вида. Указав всё в AndroidManifest, нам нужно написать обработчик получения данных из ссылки в нашей Activity.

Через getIntent.getDataString() мы можем получить нашу ссылку, достать от туда id пользователя и загрузить его профиль. Посмотрим как это выглядит в действии.

Не удалось загрузить изображение Не удалось загрузить изображение Не удалось загрузить изображение

iOS

Если вы заинтересовались этой частью статьи, значит вам необходимо привести потенциальные Web -> iOS-App ссылки в рабочее состояние, и вы пока не знаете, как это сделать.

Я расскажу о том, как сделать это при помощи Swift 3. Наиболее популярных и распространенных вариантов два: Deep Links и Universal Links. Сотрудники Apple и подавляющее большинство iOS-разработчиков скажут вам с ходу, что в сторону Deep Links не стоит даже смотреть. И в принципе, они окажутся правы, потому что Universal Links на то и Universal, т.к. они гораздо более гибкие, чем Deep Links. Единственным преимуществом в плане гибкости Deep Links является поддержка iOS: Universal Links не поддерживают операционные системы старше iOS9.

Но не рассказать о Deep Links будет по меньшей мере неправильно, так как их использование очень распространено в связях App -> App.

Deep Links

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

Итак, приступим. Для начала, вам стоит определится с идентификатором вашей URL-схемы. Сразу обращаю внимание, она должна быть уникальной. Вы должны быть полностью уверены, что больше ни одно приложение не использует подобный идентификатор, так как ссылки на приложение будут начинаться именно с него. Это одна из главных проблем Deep Links, но об этом позже.

Шаг 1

Чтобы привязать URL-схему, откройте в Xcode ваше приложение и перейдите в файл Info.plist. Если в нем еще нет строки с ключом URL types, создайте ее, нажав на пустом месте под существующими строками файла правой клавишей, выбрав Add Row и в появившемся списке ключей выбрав URL types. Раскройте строку URL types, внутри нее уже должна быть строка Item 0(если нет, опять же, создайте ее подобным вышеуказанному методом, все последующие строки при их отсутствии вы так же должны будете создать сами), раскройте ее. Установите Document Role значение Editor, URL identifierBundleID вашего приложения(можно использовать $(PRODUCT_BUNDLE_IDENTIFIER)) и наконец первый элемент массива URL Schemes. Ему нужно присвоить то самое уникальное значение, которое никто не посмеет повторить(уж постарайтесь). Например, если вы хотите, чтобы по ссылке DeepLinkApp://* открывалось ваше приложение, то URL-scheme должна быть равна DeepLinkApp. Без ://. Получиться у вас должно примерно следующее:

Не удалось загрузить изображение

Шаг 2

Для обработки ссылки вида DeepLinkApp://app/1 (значение в данном примере может быть любым, а вид ссылки в своем приложении можете задавать сами) нужно произвести следующие действия:

  1. Создать класс-обработчик:
  2. В AppDelegate необходимо будет внести следующие изменения(функции, которых у вас нет, необходимо создать):
  3. И наконец, в контроллерах, которые должны открываться после нажатия на ту или иную Deep Link, необходимо добавить в метод ViewDidLoad() следующие строки:

Вот, собственно, и вся подготовка приложения к обработке. Теперь вы со спокойной душой можете создать ссылку вида DeepLinkApp://app/1 и наслаждаться переходом в ваше приложение. Не так уж и сложно, правда? Но вся беда в том, что подобные ссылки очень криво обрабатываются браузерами, особенно в случае отсутствия на вашем девайсе подобного приложения. А значит, нужно искать другое решение. И такое решение – Universal Links.

Universal Links

Скажу честно, я убил немало времени и нервов на корректную реализацию этой технологии, но результат мне однозначно нравится. Навыков вам потребуется побольше, чем для Deep Links. В частности, вам потребуются некоторые навыки работы с backend, чтобы ссылки вашего домена корректно реагировали на нажатие. Все необходимые действия описаны в разделе, посвященном серверной работе с Universal Links.

Технология имеет огромное преимущество перед Deep Links, основные же моменты этого преимущества состоят вот в чем:

  • Безопасный маппинг к выбранным вами приложениям. У вас не будет случаев, когда у какого-то приложения прописана такая же URL-схема;
  • Универсальная работа. Если ваше приложение не установлено на устройстве, ссылка просто переведет вас на указанный адрес в браузере. А при помощи всего одной строки в файле ассоциации домена(Backender вам расскажет), добавляющей мета-ссылку, вы получите возможность перейти в AppStore с помощью Smart Banner. И это здорово;
  • Защита вашей информации. При переходе по Deep Links вы не всегда уверены в том, куда вы переходите и что передаете. Universal Links позволяют защитить вашу информацию, а также при добавлении webcredentials без проблем пользоваться сервисом как из браузера, так и из приложения, оперируя вашими входными данными.

Что же вам необходимо сделать со стороны iOS-разработчика?

Шаг 1

На сайте https://developer.apple.com/ переходите в раздел Account, выбираете team, к которой привязано ваше приложение, жмете Certificates, Identifiers & Profiles(либо посередине, либо в левом боковом меню), в левом боковом меню в разделе Identifiers выбираете App IDs и в появившемся списке раскрываете строку с вашим приложением. Включаете функцию Associated Domains, сохраняете. Обновляете свои provisioning profiles(способов это сделать много, каждый выбирает свой в соответствии с проектом, поэтому конкретно это я описывать не буду).

Не удалось загрузить изображение

Шаг 2

Чтобы понять, насколько все удачно прошло, нужно сделать второй шаг. Открываем Xcode, выбираем в навигации проекта файл с названием своего проекта, в открывшемся окне, в левой части выбираем среди Targets тот, что имеет название вашего проекта и после перехода на него, выбираем вверху вкладку Capabilities. Раскрываем строчку Associated Domains, меняем свитч справа на состояние “On”. Появится пустой список доменов. Под ним жмем «+» и прописываем необходимый домен. Например, если вы хотите, чтобы при нажатии на ссылку типа https://example.com/* устройство открывало приложение, нужно указать applinks:example.com. То есть, получиться у вас должно следующее:

Не удалось загрузить изображение

Хочу сразу обратить ваше внимание: www.example.com и example.com – разные домены. Чтобы обрабатывать оба, нужно к тому, что мы уже сделали, добавить applinks:www.example.com. Или, если вы хотите обрабатывать все субдомены, applinks:*.example.com. Также очень важно знать, что ссылка никогда не переведет пользователя в приложение, если она размещена на странице с идентичным доменом. Как я уже сказал, www.example.com и example.com – разные домены, а значит, разместив на example.com ссылку типа www.example.com/* вы сможете перейти в приложение(если конечно, она соответствует paths, указанным на сервере).

Если при включении этой функции в проекте у вас не выскочили ошибки под списком доменов, то первый шаг прошел успешно. Если же они выскочили, вероятнее всего, вы подключили функцию не для той команды, не для того приложения(бандла) или просто не обновили profiles.

Шаг 3

Теперь, собственно, то, к чему вы, как iOS-разработчик, привыкли: handling того, что отловило ваше приложение при нажатии на корректную ссылку.

Для начала в AppDelegate необходимо добавить(или модифицировать) методы:

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

Итак, какие знания для вас являются необходимыми, чтобы не попасть в просак:

  • Deep Links лучше не использовать для связи Web -> App, только для App -> App;
  • Для правильной работы Deep Links необходима абсолютно уникальная URL-scheme, не включающая в себя «://«;
  • Universal Links поддерживают только iOS9+;
  • Universal Links позволяют открывать указанную страницу в браузере, если она не обрабатывается в приложении или приложение не установлено;
  • Universal Links не откроет приложение по ссылке домена example.com, если переход по этой ссылке происходит из страницы с доменом example.com, а также если вы просто вставили необходимую для перехода ссылку в адресную строку браузера;
  • Universal Links позволяют приложению обработать входные данные в любом виде.

Собственно, на этом iOS-часть увлекательнейшего процесса окончена. Удачи вам в привязке ваших приложений к Web-сервисам и прочих ваших начинаниях. И да прибудет с вами Swift.

Читать и комментировать