Site icon AppTractor

Реализуем Универсальные ссылки на iOS

Универсальные ссылки (Universal Links) позволяют вам ссылаться на содержимое внутри вашего приложения, когда пользователь открывает определенный URL. По умолчанию веб-страницы открываются в браузере приложения, но вы можете настроить определенные пути, чтобы они открывались в вашем приложении, если оно установлено у пользователя.

Перенаправление пользователей в ваше приложение рекомендуется для того, чтобы предоставить им наиболее целостный мобильный опыт. Отличным примером является приложение WeTransfer, которое автоматически открывает URL-адреса передачи файлов, позволяя приложению скачивать их, используя наиболее эффективные системные API. В противном случае пользователям пришлось бы загружать файлы через Safari, что является гораздо менее целостным опытом. Давайте посмотрим, как можно добавить поддержку универсальных ссылок.

Разница между глубокими ссылками и универсальными ссылками

Прежде чем мы погрузимся в Универсальные ссылки, необходимо понять разницу с глубокими ссылками. Разницу лучше всего объяснить, взглянув на формат URL:

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

Для пользователей лучше использовать универсальные ссылки, чтобы гарантировать, что они найдут то, что ищут. Если вы не можете предоставить веб-вариант контента, на который вы ссылаетесь, вы можете рассмотреть возможность создания App Clip и повторного использования кода вашего основного приложения.

Поддержка универсальных ссылок

Когда пользователи нажимают универсальную ссылку, система перенаправляет их непосредственно на ваше приложение без маршрутизации через Safari или ваш сайт. Чтобы это работало, необходимо установить двустороннюю связь между вашим приложением и доменом. Для этого на ваш сайт добавляется так называемый файл ассоциированного домена.

Добавление файла на сайт

Файл ассоциированного домена содержит информацию о вашем приложении и доменах, которые поддерживает ваше приложение. Он проверяется системой, когда пользователи устанавливают ваше приложение, чтобы убедиться, что URL-адреса открываются правильно. Вы обеспечиваете безопасность ассоциации вашего приложения и веб-сайта, поскольку только вы можете хранить этот файл на своем сервере.

Вы можете найти пример такого файла для приложения Stock Analyzer: https://stock-analyzer.app/.well-known/apple-app-site-association.

Файл выглядит следующим образом:

{
    "applinks": {
        "details": [{
            "appIDs": ["4QMDKC8VLJ.com.swiftlee.StockAnalyzer"],
            "components": [{
                "/": "/stock/*",
                "comment": "Matches any URL whose path starts with /stock/"
            }]
        }]
    },
    "appclips": {
        "apps": [
            "4QMDKC8VLJ.com.swiftlee.StockAnalyzer.Clip"
        ]
    }
}

В данном случае видно, что любой URL, содержащий путь /stock/*, откроется в Stock Analyzer, если у пользователя установлено это приложение. Массив компонентов может быть настроен несколькими способами, для чего Apple приводит несколько примеров:

Вы можете настроить несколько идентификаторов приложений, которые оформляются следующим образом:

{
  "applinks": {
      "details": [
           {
             "appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
             "components": [
               {
                  "#": "no_universal_links",
                  "exclude": true,
                  "comment": "Matches any URL with a fragment that equals no_universal_links and instructs the system not to open it as a universal link."
               },
               {
                  "/": "/buy/*",
                  "comment": "Matches any URL with a path that starts with /buy/."
               },
               {
                  "/": "/help/website/*",
                  "exclude": true,
                  "comment": "Matches any URL with a path that starts with /help/website/ and instructs the system not to open it as a universal link."
               },
               {
                  "/": "/help/*",
                  "?": { "articleNumber": "????" },
                  "comment": "Matches any URL with a path that starts with /help/ and that has a query item with name 'articleNumber' and a value of exactly four characters."
               }
             ]
           }
       ]
   }
}

Файл должен использовать имя apple-app-site-association (без расширения), и вы должны загрузить его в папку под названием .well-known. Наконец, вы должны убедиться, что файл использует https:// с действительным сертификатом и без редиректов.

Ассоциирование приложения с вашим доменом

Вы можете связать свое приложение с доменом, добавив право на ассоциированные домены, нажав кнопку + Capability в Xcode:

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

Приложение My Stock Analyzer поддерживает только один домен для универсальных ссылок (applinks:) и App Clips (appclips:). Вы должны обеспечить наличие записи для каждого связанного с доменом файла.

Работа с поддоменами

Ваш сайт может поддерживать несколько поддоменов, например example.com и www.example.com. В этом случае необходимо добавить запись для каждого домена внутри связанного с доменом файла и самого приложения.

Работа с универсальными ссылками внутри вашего приложения

Вы можете работать с универсальными ссылками внутри вашего приложения, добавив модификатор openURL в представления SwiftUI или реализовав специальный метод AppDelegate. Для получения более подробной информации вы можете прочесть раздел о конфигурации в моей статье о глубоких ссылках.

Вот краткое содержание на примере приложения с рецептами.

Обработка входящих ссылок

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

Можно перевести запрос в новый метод handleIncomingURL, который мы будем вызывать из модификатора SwiftUI onOpenURL:

struct ContentView: View {

    /// We store the opened recipe name as a state property to redraw our view accordingly.
    @State private var openedRecipeName: String?

    var body: some View {
        VStack {
            Text("Hello, recipe!")

            if let openedRecipeName {
                Text("Opened recipe: \(openedRecipeName)")
            }
        }
        .padding()
        /// Responds to any URLs opened with our app. In this case, the URLs
        /// defined inside the URL Types section.
        .onOpenURL { incomingURL in
            print("App was opened via URL: \(incomingURL)")
            handleIncomingURL(incomingURL)
        }
    }

    /// Handles the incoming URL and performs validations before acknowledging.
    private func handleIncomingURL(_ url: URL) {
        guard url.scheme == "recipeapp" else {
            return
        }
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
            print("Invalid URL")
            return
        }

        guard let action = components.host, action == "open-recipe" else {
            print("Unknown URL, we can't handle this one!")
            return
        }

        guard let recipeName = components.queryItems?.first(where: { $0.name == "name" })?.value else {
            print("Recipe name not found")
            return
        }

        openedRecipeName = recipeName
    }
}

Мы добавили SwiftUI View Modifier для обработки любых входящих URL-адресов. Метод handleIncomingURL содержит проверку требований и извлекает название рецепта после подтверждения правильной структуры URL. Как только мы установим openRecipeName в полученное имя рецепта, мы перерисуем наше представление и представим значение в текстовом элементе.

Обработка URL-адресов внутри AppDelegate или SceneDelegate

Вы также можете работать с глубокими ссылками внутри AppDelegate, используя следующую функцию:

func application(_ application: UIApplication,
                     open url: URL,
                     options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    /// Handle the URL property accordingly
}

Или внутри делегата SceneDelegate, извлекая URL из параметров подключения:

func scene(_ scene: UIScene,
           willConnectTo session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions) {
    guard let url = connectionOptions.urlContexts.first?.url {
        return
    }

    /// Handle the URL property accordingly
}

Тестирование универсальных ссылок

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

После установки RocketSim вы можете открыть его окно настроек и добавить новую группу Deeplinks Group:

Очень важно настроить идентификатор пакета в соответствии с вашим приложением, чтобы быстрые действия появились в разделе Recent Builds в RocketSim (я покажу это позже). Во-вторых, вам нужно добавить новую универсальную ссылку с помощью кнопки «Добавить» в правом нижнем углу:

После создания группы с универсальными ссылками и соответствующим идентификатором пакета вы можете получить доступ к URL-адресам непосредственно рядом с симулятором:

Теперь вам нужно будет только нажать кнопку быстрого действия, чтобы открыть URL-адрес внутри вашего приложения. RocketSim отлично подходит для таких случаев и позволяет сделать то же самое для тестирования местоположения, push-уведомлений или режима самолета.

Заключение

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

Спасибо!

Источник

Exit mobile version