Как подключить мобильный SDK к приложению React Native или Expo

Обновлено: 9 октября 2026 · 10 мин чтения

Пакет @clomni/react-native работает поверх нативных SDK для Android и iOS, экраны нативные.

Шаги

  1. 1

    Требования

    • React Native 0.75 или новее (0.76 для New Architecture). Expo SDK 52 или новее, с development build.
    • iOS 15, Android 6.0 (API 23).
    • App ID и оба ключа API (android_…, ios_…).
    • Голосовым сообщениям (с SDK 1.0.2) нужно RECORD_AUDIO в манифесте Android-приложения, иначе кнопка микрофона не показывается. Камере разрешение не нужно.
  2. 2

    Установка

    npm install @clomni/react-native
    cd ios && pod install

    Остальное делает autolinking. На Android модуль берёт ai.clomni:messenger из Maven Central. На iOS pod install добавляет SDK как Swift package (spm_dependency из React Native), Xcode скачивает его при первой сборке.

    На React Native старше 0.75 pod install останавливается с «@clomni/react-native needs React Native 0.75 or later». Обновите React Native или добавьте в Podfile строку ниже. Ту же строку добавьте, если линковка падает на символах ClomniMessenger или если push подключается в нативном коде:

    # ios/Podfile, in your app's target
    pod 'ClomniMessenger', :git => 'https://github.com/clomni/clomni-mobile-sdk.git', :tag => '1.0.4'
  3. 3

    Expo

    Expo Go не загружает нативные модули. Используйте development build: npx expo prebuild, npx expo run:ios или run:android, либо сборку EAS. Config plugin пакета записывает в нативные проекты всё нужное:

    // app.config.ts
    export default {
      // ...
      plugins: [
        ['@clomni/react-native', {
          photoLibraryPermission: 'To send photos to support',       // iOS
          cameraPermission: 'To take a photo and send it to support', // iOS
          push: true,                                                 // the default
          notificationIcon: './assets/notification-icon.png',         // Android, white silhouette PNG
        }],
      ],
    };

    push: true добавляет на iOS entitlement aps-environment и background mode remote-notification, на Android разрешение POST_NOTIFICATIONS. Иконка становится drawable с именем clomni_notification_icon. В обычном приложении без Expo добавьте два текста разрешений для фото в Info.plist сами: NSPhotoLibraryUsageDescription и NSCameraUsageDescription.

  4. 4

    Запустите SDK

    Один раз, вне компонентов. index.js подходит лучше всего, потому что push может запустить приложение без экрана.

    // index.js
    import { AppRegistry, Platform } from 'react-native';
    import Clomni from '@clomni/react-native';
    import App from './App';
    import { name as appName } from './app.json';
    
    Clomni.initialize('app_…', Platform.OS === 'ios' ? 'ios_…' : 'android_…');
    if (__DEV__) Clomni.setLogLevel('debug');
    
    AppRegistry.registerComponent(appName, () => App);

    Третий параметр initialize называется region, по умолчанию 'eu'. Сейчас есть только 'eu', передавать его не нужно: любое другое значение SDK пишет в лог и использует 'eu'.

  5. 5

    Пользователь и Messenger

    Clomni.loginUser({ userId: '12345', email: '[email protected]', name: 'Aysel' }, hashFromYourServer);
    Clomni.updateUser({ language: 'az', customAttributes: { plan: 'premium' } });
    
    // Together with your app's own logout:
    Clomni.logout();
    import { useEffect, useState } from 'react';
    import { Pressable, Text } from 'react-native';
    import Clomni from '@clomni/react-native';
    
    export function SupportRow() {
      const [unread, setUnread] = useState(0);
    
      useEffect(() => {
        // The current count at once, then every change.
        const subscription = Clomni.addEventListener('unreadCountChanged', setUnread);
        return () => subscription.remove();
      }, []);
    
      return (
        <Pressable onPress={() => Clomni.present('profile_support')}>
          <Text>Support{unread > 0 ? ` (${unread})` : ''}</Text>
        </Pressable>
      );
    }

    Другие вызовы: presentNewConversation(source), presentConversation(id), dismiss(), setLauncherVisible(true), setBottomPadding(72). События через addEventListener: messengerOpened, messengerClosed, conversationStarted, flowCompleted. Колбэки нативного SDK модуль забирает сам, не назначайте их отдельно в нативном коде.

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

    Для пользователя, который не вошёл, ничего вызывать не нужно: Messenger сам создаёт анонимного посетителя при открытии. Clomni.loginUnidentifiedUser() делает это заранее. Посетитель остаётся тем же на этом устройстве до logout, а при вызове loginUser его диалоги переходят к пользователю.

  6. 6

    Flow, события, ссылки и внешний вид

    Запуск flow из приложения и события Messenger:

    Clomni.startFlow('ride_problem', { ride_id: 'R-1923' }, { openMessenger: true, source: 'ride_screen' });
    
    const subscriptions = [
      Clomni.addEventListener('messengerOpened', (source) => console.log('opened from', source)),
      Clomni.addEventListener('messengerClosed', () => console.log('closed')),
      Clomni.addEventListener('conversationStarted', (id) => console.log('conversation', id)),
      Clomni.addEventListener('flowCompleted', (flowId) => console.log('flow', flowId)),
    ];
    // later: subscriptions.forEach((s) => s.remove());

    В панели нужен flow с триггером «App event» и тем же именем, и он должен быть опубликован. Данные должны быть JSON. Модуль сам управляет событиями нативного SDK: не задавайте их ещё и в нативном коде приложения.

    Ссылки, язык, звуки и собственный цвет приложения:

    import { Linking } from 'react-native';
    
    Clomni.onLink((url) => Linking.openURL(url));   // or your own router; null: the system opens links
    Clomni.setLanguage('en');                       // 'az', 'en', 'ru'; null follows the phone
    Clomni.setSoundsEnabled(false);
    Clomni.setTheme({ primaryColor: '#0A66C2', typeface: 'Montserrat', mode: 'dark' });

    Шрифт задаётся именем семейства, которое Вы используете в стилях fontFamily. На iOS шрифт должен быть в приложении и указан под UIAppFonts, на Android React Native ищет его в android/app/src/main/assets/fonts или res/font. Только шрифт: Clomni.setTypeface('Montserrat'). Значение из панели действует, только если приложение не задало своё.

  7. 7

    Push: Android

    Сначала загрузите ключи в панель (статья «Ключи push для мобильного SDK»). Настройте Firebase с google-services.json и плагином Google services для Gradle, как описано в документации React Native Firebase. Затем:

    // index.js, next to initialize
    import messaging from '@react-native-firebase/messaging';
    
    // Clomni data messages while the app is in the background or closed: the SDK shows the notification.
    messaging().setBackgroundMessageHandler(async (message) => {
      Clomni.handlePush(message.data ?? {});
    });
    // App.tsx
    import { useEffect } from 'react';
    import { PermissionsAndroid, Platform } from 'react-native';
    import messaging from '@react-native-firebase/messaging';
    import Clomni from '@clomni/react-native';
    
    useEffect(() => {
      if (Platform.OS !== 'android') return;
      PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);   // Android 13+
      messaging().getToken().then((token) => Clomni.setDeviceToken(token));
      const unsubscribeToken = messaging().onTokenRefresh((token) => Clomni.setDeviceToken(token));
      // Messages while the app is open.
      const unsubscribeMessage = messaging().onMessage(async (message) => {
        if (!Clomni.handlePush(message.data ?? {})) {
          // your app's own push
        }
      });
      Clomni.setNotificationIcon('clomni_notification_icon');   // the config plugin's notificationIcon
      return () => { unsubscribeToken(); unsubscribeMessage(); };
    }, []);

    В обычном приложении объявите <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> в AndroidManifest.xml, положите белую иконку в android/app/src/main/res/drawable/ и передайте её имя в setNotificationIcon.

  8. 8

    Push: iOS

    Clomni отправляет push на iOS напрямую в APNs, не через Firebase. Библиотека Firebase сообщает только о сообщениях FCM и не видит нажатия на уведомление Clomni. Поэтому ловите нажатие в нативном коде:

    1. Добавьте в Xcode capability Push Notifications.
    2. Добавьте строку pod 'ClomniMessenger' выше в ios/Podfile и выполните pod install.
    3. Добавьте этот файл в цель приложения:
    // ios/<YourApp>/ClomniNotifications.swift
    import ClomniMessenger
    import UserNotifications
    
    /// Clomni pushes: hidden while the Messenger is open, and a tap opens the conversation.
    @objc(ClomniNotifications)
    final class ClomniNotifications: NSObject, UNUserNotificationCenterDelegate {
        @objc static let shared = ClomniNotifications()
    
        func userNotificationCenter(
            _ center: UNUserNotificationCenter,
            willPresent notification: UNNotification,
            withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
        ) {
            let show = Clomni.shouldShowForeground(notification.request.content.userInfo)
            completionHandler(show ? [.banner, .list, .sound] : [])
        }
    
        func userNotificationCenter(
            _ center: UNUserNotificationCenter,
            didReceive response: UNNotificationResponse,
            withCompletionHandler completionHandler: @escaping () -> Void
        ) {
            _ = Clomni.handlePush(response.notification.request.content.userInfo)
            completionHandler()
        }
    }
    1. Сделайте его делегатом в application(_:didFinishLaunchingWithOptions:), до возврата из метода:
    // AppDelegate.swift
    UNUserNotificationCenter.current().delegate = ClomniNotifications.shared
    // AppDelegate.mm, when the app delegate is Objective-C
    #import "YourApp-Swift.h"
    #import <UserNotifications/UserNotifications.h>
    
    [UNUserNotificationCenter currentNotificationCenter].delegate = ClomniNotifications.shared;

    React Native Firebase затем берёт делегат на себя и передаёт этому делегату каждый чужой для него push, так что Ваши push через FCM продолжают работать.

    1. Передайте токен APNs из JavaScript:
    if (Platform.OS === 'ios') {
      await messaging().requestPermission();
      const apnsToken = await messaging().getAPNSToken();   // hex
      if (apnsToken) Clomni.setDeviceToken(apnsToken);
    }

    Если на iOS нет Firebase, передайте токен в нативном коде: Clomni.setDeviceToken(deviceToken) в didRegisterForRemoteNotificationsWithDeviceToken. В Expo папку ios создаёт prebuild: держите шаги 3 и 4 в своём небольшом config plugin (withAppDelegate, withXcodeProject) или храните папку ios в репозитории.

  9. 9

    Проблемы

    • «The package doesn't seem to be linked» или нативный модуль не найден: пересоберите приложение; в Expo используйте development build.
    • Ошибки линковки на символах ClomniMessenger на iOS: строка pod 'ClomniMessenger' в Podfile и pod install.
    • На Android уведомления не приходят, когда приложение закрыто: setBackgroundMessageHandler должен быть в index.js, вне компонентов.
    • На iOS нажатие на уведомление Clomni только открывает приложение: нативного делегата (шаги 3 и 4) нет или он назначен слишком поздно.
    • Плавающая кнопка не появляется при холодном запуске приложения. Причина: ошибка SDK 1.0.1, исправлено в 1.0.2. До этого открывайте Messenger своей кнопкой.
    • Android: открытый Messenger пропадает, когда приложение снова открывают по иконке. Причина: MainActivity с singleTask. Исправлено в SDK 1.0.2.
  10. 10

    Полное руководство

Документ