# Работа с мобильными пушами

Порядок интеграции push уведомлений для Android и iOS.

# Структура push-уведомлений

Пример payload для push-уведомления:

{
  "id": "sample_id",
  "title": "Заголовок уведомления",
  "body": "Текст уведомления.",
  "icon": "https://example.com/icons/sample_icon.png",
  "type": "тип_уведомления",
  "actions": [
    {
      "action": "open_app",
      "title": "Открыть приложение"
    },
    {
      "action": "view_details",
      "title": "Посмотреть детали"
    }
  ],
  "actionUrls": [
    "https://example.com/action1",
    "https://example.com/action2"
  ],
  "image": "https://example.com/images/sample_image.png",
  "event": {
    "type": "web",
    "uri": "https://example.com/event",
    "payload": {
      "campaignId": "campaign_sample",
      "userSegment": "segment_sample"
    }
  },
  "recipient": {
    "userId": "user_sample_id",
    "deviceToken": "sample_device_token"
  },
  "priority": "high",
  "timestamp": "2024-12-18T12:00:00Z"
}

# Android

Первый шаг - добавление разрешений для Push-уведомлений. Для этого вам нужно добавить разрешения в AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

Важно убедиться, что служба Firebase Messaging указана в манифесте. Вот пример того, как это должно выглядеть:

<service android:name="com.google.firebase.messaging.FirebaseMessagingService" android:exported="true">
  <intent-filter>
    <action android:name="com.google.firebase.MESSAGING_EVENT" />
  </intent-filter>
</service>

# Обработка уведомлений

# Слушатель уведомлений и интерфейс их обработки

Установка слушателя для входящих уведомлений:

sdk.setOnMessageListener(
  listener = { data ->
    Log.i(TAG, data.toString())
  }
)

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

fun interface OnMessageListener {
  fun onMessage(data: NotificationData)
}

Реализация метода onMessage позволяет задать конкретные действия, которые должны выполняться при получении уведомления (например, открыть экран, показать баннер или обновить данные на экране).

Разработчик должен реализовать логику обработки в методе onMessage.

# Класс NotificationData

Класс NotificationData это "контейнер" данных уведомления, который упрощает работу с payload.

data class NotificationData(
  val id: String?,
  val title: String?,
  val body: String?,
  val icon: String?,
  val type: String?,
  val actions: List<NotificationAction>?,
  val actionUrls: List<String>?,
  val image: String?,
  val event: NotificationEvent?
)

# Класс NotificationAction

Класс NotificationAction описывает действия, доступные в уведомлении.

data class NotificationAction(
  val action: String,
  val title: String
)

Этот класс используется в поле actions объекта NotificationData, чтобы определить логику выполнения сценария.

action - идентификатор действия, который приложение использует при отработке сценария.

# Класс NotificationEvent

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

data class NotificationEvent(
  val type: String?,
  val uri: String?,
  val payload: Map<String, Any>? = null
)

# iOS

Для настройки push-уведомлений на iOS выполните следующие действия:

  1. Включите возможность Push Notifications в проекте Xcode в разделе Signing & Capabilities.
  2. Зарегистрируйте приложение для получения push-уведомлений в файле AppDelegate.swift:
import UserNotifications
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    UNUserNotificationCenter.current().delegate = self
    application.registerForRemoteNotifications()
    FirebaseApp.configure()
    return true
  }
}
  • Метод didRegisterForRemoteNotificationsWithDeviceToken вызывается, когда устройство успешно зарегистрировалось для получения push-уведомлений.
  • deviceToken — это уникальный токен устройства, который используется сервером для отправки уведомлений на конкретное устройство.

# Обработка уведомлений, полученных в активном состоянии (приложение запущено)

Следующий метод позволяет разработчику контролировать видимость уведомления, особенно в активном приложении. Например, можно показать всплывающее окно или обновить данные на экране.

func userNotificationCenter(
  _ center: UNUserNotificationCenter,
  willPresent notification: UNNotification,
  withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
  completionHandler([.alert, .badge, .sound])
}

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

# Обработка уведомлений в фоновом режиме

Этот метод вызывается, когда приложение получает уведомление в фоновом режиме или когда уведомление содержит данные, требующие фоновой обработки.

func application(
  _ application: UIApplication,
  didReceiveRemoteNotification userInfo: [AnyHashable: Any],
  fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
  print("Received Notification: \(userInfo)")
  completionHandler(.newData)
}

# Реализация пользовательских действий

Реализация протокола NotificationActionsProtocol для обработки пользовательских действий, заданных в уведомлении.

Вместо print разработчик должен разместить код для выполнения действия.

Каждый метод обрабатывает определённое действие:

  1. openCustom(url: String) — открывает пользовательский URL
  2. openCategory(categoryId: String) — открывает категорию с указанным идентификатором
  3. openProduct(productId: String) — открывает страницу продукта
  4. openWeb(url: String) — открывает веб-страницу
extension AppDelegate: NotificationActionsProtocol {
  func openCustom(url: String) {
    print("Open custom URL: \(url)")
  }

  func openCategory(categoryId: String) {
    print("Open category: \(categoryId)")
  }

  func openProduct(productId: String) {
    print("Open product: \(productId)")
  }

  func openWeb(url: String) {
    print("Open web URL: \(url)")
  }
}