Skip to content

Push-уведомления

Убедитесь, что предыдущие шаги выполнены успешно
  • SDK добавлено в ваше мобильное приложение
  • Ключи взяты из раздела для разработчика: Ключи для SDK
  • Инициализация выполнена успешно
Результат шага
  • В приложении настроена отправка push-уведомлений через Firebase Cloud Messaging

Для работы с push-уведомлениями Carrot quest SDK для Flutter использует Firebase Cloud Messaging. Необходимо настроить FCM и передать токен в Carrot quest.

Подключение Firebase

Если вы еще не используете FCM в проекте, добавьте зависимости:

yaml
dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.15.0
  firebase_messaging: ^14.6.5

После этого выполните:

shell
flutterfire configure

Подробная инструкция по настройке Firebase для Flutter: firebase.google.com

Обработка push в фоне

В main.dart добавьте background handler. Внутри него нужно передавать Carrot-пуши в SDK:

dart
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  final bool isCarrotPush = Carrot.isCarrotQuestPush(message.data);
  if (isCarrotPush) {
    Carrot.sendFirebasePushNotification(message.data);
  }
}

Передача FCM-токена в SDK

После инициализации Carrot quest SDK отправьте токен Firebase через Carrot.sendFcmToken(token).

Перед отправкой токена убедитесь, что пользователь дал разрешение на показ уведомлений. Без этого токен не будет записан на сервере.

Пример инициализации:

dart
Future<void> initCarrotSdk() {
  return Carrot.setup(apiKey, appGroup: appGroup).then((isInit) async {
    if (!isInit) {
      return;
    }

    if (await notificationService.checkPermissions()) {
      await initFcm();
    }

    Carrot.getUnreadConversationsCountStream().listen((count) {
      unreadConversationsCount = count;
    });
  });
}

Future<void> initFcm() async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  FirebaseMessaging.onBackgroundMessage(
    _firebaseMessagingBackgroundHandler,
  );

  final String? token = await FirebaseMessaging.instance.getToken();

  if (token != null && token.isNotEmpty) {
    await Carrot.sendFcmToken(token);

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      final bool isCarrotPush = Carrot.isCarrotQuestPush(message.data);
      if (isCarrotPush) {
        Carrot.sendFirebasePushNotification(message.data);
      }
    });
  }
}

Дополнительная настройка для iOS

Для устройств Apple нужно запросить разрешение на показ уведомлений в нативной iOS-части проекта. Откройте AppDelegate.swift и добавьте запрос разрешений:

swift
override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    GeneratedPluginRegistrant.register(withRegistry: self)

    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { _, _ in }
        )
    } else {
        let settings = UIUserNotificationSettings(
            types: [.alert, .badge, .sound],
            categories: nil
        )
        application.registerUserNotificationSettings(settings)
    }

    application.registerForRemoteNotifications()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

Затем добавьте расширение для обработки показа и нажатия уведомлений:

swift
import CarrotSDK

extension AppDelegate: UNUserNotificationCenterDelegate{

    override func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        let notificationService = CarrotNotificationService.shared
        if notificationService.canHandle(notification) {
            notificationService.show(
                notification,
                appGroudDomain: "GROUP ID",
                completionHandler: completionHandler
            )
        } else {
            // Логика для пользовательских уведомлений
        }
    }

    override func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        let notificationService = CarrotNotificationService.shared
        if notificationService.canHandle(response) {
            notificationService.clickNotification(
                notificationResponse: response,
                appGroudDomain: "GROUP ID"
            )
        } else {
            // Логика для пользовательских уведомлений
        }
    }

    private func getAppGroup() -> String {
        return "<group_id>" // замените на ваш App Group ID, если используется
    }
}

Параметр appGroudDomain используется только если вы настраивали App Group. Если App Group не нужен — передайте пустую строку или исключите параметр.

Также для предотвращения дублей уведомлений можно использовать App Group и Notification Service Extension.

Когда нужен App Group

Carrot quest SDK для Flutter использует два канала доставки сообщений, поэтому в отдельных сценариях уведомления могут дублироваться, например:

  • при выходе из приложения
  • при быстром удалении уведомления

Если дублей нет, этот шаг можно пропустить.

Что нужно сделать

  1. Создать Notification Service Extension в Xcode.
  2. Зарегистрировать App Group в Apple Developer Portal.
  3. Добавить один и тот же App Group и в основное приложение, и в Notification Service Extension.
  4. Передать appGroup в Carrot.setup().

Пример инициализации с appGroup:

dart
await Carrot.setup(apiKey, appGroup: groupId);

Логика для Notification Service Extension

В нативной iOS-части создайте файл NotificationService.swift в папке расширения:

swift
import UserNotifications
import CarrotSDK

class NotificationService: CarrotNotificationServiceExtension {
    override func setup() {
        self.domainIdentifier = "<group_id>" // тот же App Group ID
    }

    override func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
    ) {
        // ваша логика
        super.didReceive(request, withContentHandler: contentHandler)
    }
}

Настройка Podfile

Проверьте, что для Notification Service Extension добавлен отдельный target в Podfile:

ruby
target 'NotificationService' do
    inherit! :search_paths
end

Иконка уведомлений на Android

Для Android можно заменить иконку уведомлений. Для этого добавьте в Android-часть проекта файл ic_cqsdk_notification.xml.

Уведомления на iOS

Чтобы FCM корректно работал на iOS, добавьте в Info.plist вашего проекта:

xml
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>

Это переключает управление уведомлениями в ручной режим и позволяет SDK правильно функционировать. Подробнее — в документации Firebase.