Головна / Статті / Надсилання сповіщень через дейлінки в React Native

Надсилання сповіщень через дейлінки в React Native

Налаштуйте універсальні посилання та посилання додатків, під’єднайте Pusher Beams до додатку React Native та прив’яжіть веб-URL до нативних екранів, щоб натискання на сповіщення відкривало потрібне місце.

1898 слів

Повідомлення типу push є корисним лише тоді, коли його натискання переносить користувача на екран, про який воно йдеться. Уявіть собі додаток React Native для міжнародних студентів, які обирають коледжі: електронні листи залишаються непрочитаними, а SMS є ненадійним у різних країнах, тому повідомлення типу push мають працювати, коли звертається керівник з пропозицією. Тут ви налаштуєте глибоке посилання на обох платформах, додасте URL веб-сайту до кожного повідомлення Pusher Beams та перетворите цей URL на маршрут React Navigation, протестуючи кожен етап на шляху.

Чому глибокі посилання визначають місце призначення повідомлення

На момент створення цієї конфігурації пакети Pusher, які тут використовувалися, не могли передавати користувацький вміст сповіщення на JavaScript-частину додатку React Native для Android. Найпростішим рішенням, подібним до запиту на зміни до Android SDK, є використання глибокого посилання: сповіщення в Android містить звичайне посилання на веб-сайт, клік на нього обробляється як клік по цьому посиланню, а наявна система обробки глибоких посилань у додатку визначає, який екран відкрити.

З того часу ситуація могла змінитися, тому спочатку перевірте поточні версії Beams SDK. Шар маршрутизації у будь-якому випадку є корисним, оскільки він також обробляє посилання з електронної пошти, SMS чи чату.

Короткий огляд глибокого посилання

Глибоке посилання дозволяє додатку отримувати посилання на ваш власний веб-сайт та відкривати їх безпосередньо. Посилання на кшталт https://test.com/message/abc має відкривати додаток безпосередньо на повідомленні abc, а не запускати браузер. iOS називає це універсальними посиланнями, Android — посиланнями додатку, і в обох випадках ваш домен має опублікувати файл, який підтверджує довіру до додатку.

Налаштування глибокого посилання на обох платформах

Опублікуйте файли верифікації у директорії .well-known

Створіть директорію /.well-known/ у корені вашого веб-сайту. Для Android додайте файл /.well-known/assetlinks.json, який позначає, що ваш додаток може обробляти всі URL у цьому домені. Замініть місця заміни на назву пакета вашого додатку та SHA-256-відбиток сертифіката, який його підписує:

[{
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
        "namespace": "android_app",
        "package_name": "package_name",
        "sha256_cert_fingerprints":
        ["package_cert_fingerprint"]
    }
}]

Якщо Google Play перепідписує ваші версії додатку, використовуйте відбиток ключа підписування Play, а не вашого ключа завантаження, інакше перевірка провалиться лише у продакшен-середовищі.

Для iOS додайте файл під назвою /.well-known/apple-app-site-association (без розширення). У ньому вказується ідентифікатор вашого додатку, який поєднує ID команди та ID пакету, а також URL-шляхи, які додаток має перехоплювати:

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "appId",
                "paths": [ "/paths-you-want-to-support", "/messenger"]
            }
        ]
    }
}

Надавайте обидва файли через HTTPS з саме того домену, без перенаправлень. Це класична структура applinks; Apple згодом додала новіший формат, тому перевірте її актуальну документацію.

Увімкнення пов’язаних доменів у iOS

iOS також потребує права, яке вказує, до яких доменів належить додаток. У Xcode відкрийте Capabilities, увімкніть Associated Domains та додайте кожен домен, який ви хочете під’єднати, зазвичай у форматі applinks:yourdomain.com.

Оголошення фільтрів наміру в Android

У Android глибокі посилання оголошуються за допомогою фільтрів наміру в файлі AndroidManifest.xml. Щоб обробляти посилання у форматі /messenger/*, основній діяльності потрібен фільтр наміру для дії VIEW із категоріями DEFAULT та BROWSABLE, а також елемент data, який вказує схему https, ваш хост та префікс шляху /messenger. Додавання параметра android:autoVerify="true" примушує систему перевіряти файл assetlinks.json, щоб додаток міг відкривати ці посилання без показу діалогового вікна вибору.

Прослуховування посилань у кореневому компоненті

Основний компонент додатку повинен виконувати дві функції: читати URL, який запустив додаток під час першого запуску, та стежити за URL, які надходять під час його роботи. Модуль Linking у React Native забезпечує обидві ці функції за допомогою методу getInitialURL() та слухача подій url. Обидва механізми повинні викликати один обробник, який наразі може просто записувати URL:

const handleDeepLink = (url: string) => console.log(url);

Перевірте посилання перед додаванням сповіщень

Спочатку перевірте функцію глибокого посилання окремо, перш ніж додавати до неї функцію сповіщень. Простий спосіб — надіслати собі посилання через месенджер, такий як Slack, на кожному тестовому пристрої та натиснути на нього. Якщо конфігурація правильна, посилання відкриє ваш додаток, а не браузер, і записаний URL збігатиметься з тим, на який ви натиснули. Ізоляція цього етапу означає, що подальші проблеми з направленням сповіщень будуть пов’язані лише із проблемами типу push.

Додавання Pusher Beams до додатку

Попередні вимоги та місток спільноти

Вам потрібен обліковий запис Pusher Beams, і ви повинні пройти кроки налаштування для сервісу push від Apple та Google Firebase.

Зверніть увагу, що на момент написання цього посібника Pusher не пропонував офіційного пакета для React Native. Тут використовується пакет спільноти react-native-pusher-push-notifications, який з’єднує нативні SDK Beams із JavaScript, але не підтримується Pusher. Щоб він працював у цій конфігурації, знадобилися невеликі корективи. На Android ключовою зміною було форк SDK push-notifications-android від Pusher, який перетворює натискання на сповіщення на відкриття глибокого посилання. Використання неофіційного містка та форкованого SDK вимагає постійного догляду: потрібно фіксувати версії та переглядати вибір у разі змін офіційних SDK.

Встановіть Swift SDK на iOS

Частина для iOS залежить від Swift SDK від Pusher, який встановлюється тут за допомогою Carthage. Додайте наступний рядок до /ios/Cartfile, а потім запустіть carthage bootstrap, щоб завантажити та скомпілювати його:

github "pusher/push-notifications-swift" ~> 1.3.0

Ця версія була актуальною для цього інтегрування; нові проекти, ймовірно, будуть використовувати більш сучасний SDK та, можливо, інший менеджер залежностей.

Потім дотримуйтесь кроків ручної установки пакета-мосту для обох платформ, оскільки нативні компоненти є налаштованими індивідуально.

Надсилання тестового сповіщення

Сповіщення в iOS надходять лише на фізичні пристрої, а не на симулятори, тому тримайте під рукою справжній iPhone.

Щоб надіслати тестове сповіщення, скористайтеся консоллю для налагодження у панелі керування Pusher або HTTP-клієнтом, таким як Postman, що використовує API Beams publish. Достатньо мати тіло запиту з розділами для iOS та Android; у цьому варіанті розділ для iOS встановлює кількість значків у 5, а розділ для Android містить URL веб-сайту, який потрібно відкрити.

Якщо все налаштовано правильно, iOS сам обробляє вміст сповіщення, тоді як Android відкриває додаток за допомогою інтенту View з URL вашого веб-сайту. На обох платформах ваш обробник має записати щось на кшталт https://yourdomain/messenger/abcde. На iOS іконка додатку також має відображати значок із числом 5.

Перетворення URL на маршрути React Navigation

Останнім кроком є заміна штучного механізму логування на справжнє маршрутизування. Поширеною конфігурацією є використання React Router на веб-сайті та React Navigation у додатку React Native. Невелика утиліта, яка відповідає за перетворення веб-маршрутів у нативні, дозволяє обом компонентам спільно використовувати логіку та запобігає тому, щоб перейменована веб-адреса потайки порушувала навігацію в додатку.

Спільне використання констант маршрутів у веб-версії та нативній

У обох кодових базах маршрути визначаються як константи. У веб-версії інструмент для створення маршрутів повертає або конкретний шлях, або шаблон, за яким React Router здійснює пошук; у нативній версії еквівалентом є назва екрану, причому ідентифікатор розмови передається окремо як параметр навігації:

// Web:
ROUTE = {
    MESSENGER_CONVERSATION: (conversationId?: string) =>
        conversationId
            ? `/messenger/${conversationId}`
            : "/messenger/:conversationId"
}// Native:
APP_STACK_ROUTE: {
    MESSENGER_CONVERSATION_SCREEN:
        "app_stack_routes/messenger_conversation"
}
// native then has a params object with conversationId included

Оскільки обидві частини представлені у вигляді констант, можна у єдиній таблиці вказати, який веб-шлях відповідає якому нативному екрану:

const ROUTE_MATCHES: IRouteMatches = [
    {
        webPath: ROUTE.MESSENGER_CONVERSATION(),
        rnPath: APP_STACK_ROUTES.MESSENGER_CONVERSATION_SCREEN
    }
];

Виклик ROUTE.MESSENGER_CONVERSATION() без аргументів повертає шаблон /messenger/:conversationId, тому таблиця зберігає той самий шаблон, що використовується маршрутизатором веб-сайту. Перейменування веб-маршруту автоматично оновлює це зіставлення. Щоб ознайомитися з принципами роботи цих веб-шаблонів, перегляньте Основи React Router.

Дебаунс вхідних URL

Обробник іноді викликається більше одного разу за натискання, наприклад коли перевірка початкового URL та обробник обидва повідомляють про наявність посилання, що призводить до відображення дублікатів екранів. Передача кожного URL через RxJS Subject та застосування функції debounceTime(100) об’єднує кілька викликів у один, який потім надсилається до функції processUrl:

export const handleDeepLink = (url: string): void => {
    if (!url) return;
    onChangeUrl$.next(url);
};
const onChangeUrl$: Subject<string> = new Subject<string>();
const urlSubscription: Observable<string> = onChangeUrl$.pipe(debounceTime(100));
urlSubscription.subscribe(processUrl);

Компроміс: два різні посилання протягом 100 мс зливаються в останнє, що є прийнятним для натискань на сповіщення.

Розділіть URL на частини

processUrl спочатку розділяє URL на протокол, хост, шлях та рядок запиту за допомогою регулярного виразу (інструменти на кшталт RegExr допомагають під час налаштування). Механізм розбирання ігнорує повне зіставлення та групу запиту, яка все ще містить ?:

const REGEX_DECONSTRUCT_URL = /^(.*?):\/\/(.*?)(\/.*?)(\?(.*))?$/;const deconstructedUrl = REGEX_DECONSTRUCT_URL.exec(url);
    if (!deconstructedUrl) return;
    const [originalUrl, protocol, tld, path, ignore, querystring] = deconstructedUrl;

Зверніть увагу, що цей шаблон вимагає наявності шляху: просте https://yourdomain без кінцевої крапки-розділника не буде зіставлено, і функція повернеться раніше. Це підходить для посилань у сповіщеннях, але варто знати про це, якщо ви будете використовувати цей помічник в інших місцях.

Зіставте шлях із таблицею маршрутів

Після вилучення елементів обробник працює лише з посиланнями HTTPS у вашому домені, потім проходить через ROUTE_MATCHES, поки один з елементів не прийме цей шлях:

if (protocol === "https" && tld.includes("yourdomain")) {
    for (let i = 0; i < ROUTE_MATCHES.length; i++) {
        if (matchPath(ROUTE_MATCHES[i], path, querystring)) {
            // loop until one matches
            break;
        }
    }
}

Перевірка tld.includes("yourdomain") є зручною, але недостатньо точною: вона також прийме хост на кшталт yourdomain.attacker.example. Операційна система перевіряє універсальні та додаткові посилання, тому ризик є обмеженим, проте точний список дозволених хостів є простим способом покращення безпеки, особливо коли обробник використовується з іншими джерелами URL.

Усередині matchPath шаблон webPath перевіряється щодо надісланого шляху за допомогою path-to-regexp — тієї самої бібліотеки, від якої залежить React Router. Коли відбувається збіг, видобуті параметри, такі як conversationId, стають параметрами відповідного екрану rnPath, і додаток переміщується туди. Оскільки цей процес виконується поза межами будь-якого компонента, його запускає невеликий сервіс навігації, який зберігає посилання на кореневого навігатора, як описано в документації React Navigation для навігації без використання атрибута navigation.

Підсумок

Завдяки цим елементам додаток виконує дві функції через один шлях коду:

  • Посилання на ваш веб-сайт, незалежно від того, чи вони надійшли з електронної пошти, SMS чи чату, відкривають відповідний екран у нативному додатку.
  • Повідомлення типу push використовують ту саму логіку обробки глибоких посилань, тож один дотик відправляє користувача безпосередньо до відповідної розмови.
  • Те, що дозволяє підтримувати цю систему, — це розгляд URL веб-сайту як єдиного опису пункту призначення, з використанням таблиці для перетворення URL на вбудовані маршрути. Тестуйте кожен рівень окремо, посиліть перевірку хоста та стежте за офіційними SDK Beams: якщо вони передають дані до JavaScript, можна відмовитися від форку та зберегти рівень маршрутизації.

    Пов’язана література