Инструкция по подключению мобильных пуш-уведомлений (iOS)

1. Подключение библиотеки

Данная библиотека распространяется с помощью Cocoapods. Для ее использования в Podfile необходимо добавить зависимость:

«pod "enkodpushlibrary"» 

enkod позволяет использовать для отправки пуш-уведомлений Apple Push Notification System и Firebase Cloud Messaging. Для использования FCM необходимо импортировать библиотеку Firebase.

2. Добавление Push Notifications в проект

Необходимо добавить пуш-уведомления в ваш проект, чтобы пользователь мог получать их. Для этого зайдите в Targets на ваш проект и выберите раздел Signing & Capabilities. Далее в Capabilities добавьте Push Notifications. В этом разделе укажите ваш Team. А также укажите ваш BundleID в разделе General.

Для использования FCM в приложении необходимо загрузить GoogleService-Info.plist из консоли Firebase и поместить его в папку с приложением (предварительно в консоли должен быть добавлен сертификат .p8 для приложения).

3. Регистрация приложения в Apple Push Notification Service (APNs)

Регистрация необходима для подготовки приложения к работе с пуш-уведомлениями. Для этого добавьте в AppDelegate следующий код:

func application(_ application: UIApplication, didFinishLaunchingWithOptions 
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    PushNotificationService.setAccount("account")
    PushNotificationService.registerForPushNotifications()   
    if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] {
             PushNotificationService.notificationData(notification)
         }  
    return true
} 

При использовании FCM метод будет выглядеть следующим образом:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    PushNotificationService.setAccount("account")
    PushNotificationService.registerForPushNotifications() 
    FirebaseApp.configure()
    Messaging.messaging().delegate = self
    if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] {
             PushNotificationService.notificationData(notification)
         }  
    return true
}

где account - системное имя вашего аккаунта в enKod (запросите у персонального менеджера)

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

4. Регистрация device token приложения

Для отправки пуш-уведомления необходим device token вашего приложения. Чтобы зарегистрировать его, добавьте следующий код в AppDelegate:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    PushNotificationService.setDeviceToken(deviceToken, account: "account")
}

При использовании FCM метод будет выглядеть следующим образом:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
}               

Данный метод позволяет обработать device token и отправить его к провайдеру с заданным заголовком account.

func application(_ application: UIApplication, 
didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print("Failed to register: \(error)") 
}  

Данный метод выдаст ошибку при получении device token.

Также для использования FCM необходимо добавить следующее расширение:

extension AppDelegate: MessagingDelegate {
  func messaging( _ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?)         {
      PushNotificationService.setDeviceToken(fcmToken ?? "")
  }
}

5. Настройка обработки открытия push-уведомления

Добавьте следующий код в соответствующие методы AppDelegate:

func application(_ application: UIApplication, 
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {    
    PushNotificationService.registerForPushNotifications()
    UNUserNotificationCenter.current().delegate = self                        
    if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] {
        PushNotificationService.notificationData(notification, account: "account")
    }
    return true
}                        

Данный метод AppDelegate вызовется тогда, когда приложение полностью выгружено из памяти и происходит нажатие на уведомление. Также необходимо объявить делегата, чтобы обрабатывать и другие сценарии нажатия на пуш-уведомление.

func application(_ application: UIApplication, 
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {        
    PushNotificationService.notificationData(userInfo, account: "account")
    completionHandler(.newData)
}                
extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, 
    didReceive response: UNNotificationResponse, 
    withCompletionHandler completionHandler: @escaping () -> Void) {                        
    let notification = response.notification.request.content.userInfo
    PushNotificationService.notificationData(notification, account: "account")
    completionHandler()
    }
}  

где account - системное имя вашего аккаунта в enKod (запросите у персонального менеджера)

Данные методы AppDelegate вызываются тогда, когда приложение находится в активном состоянии и происходит нажатие на уведомление.

6. Изменение ключа в Info.plist для корректной работы URL запросов

Необходимо зайти в файл Info.plist и добавить следующий ключ со значением:

7. Настройка отображения пуш-уведомления при открытом приложении

Добавьте следующий метод UNUserNotificationCenterDelegate в AppDelegate:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification:
UNNotification, withCompletionHandler completionHandler: @escaping 
(UNNotificationPresentationOptions) -> Void) {
    if #available (iOS 14.0, *) {
        completionHandler ([. list, .banner, .sound])
    } else {
        completionHandler ([. alert, .badge, .sound])
    }
}  

Данный метод позволяет настроить появления уведомления даже при открытом приложении.

Пуш-уведомления могут содержать в себе deeplink. Для того, чтобы получить информацию о deeplink в пуш-уведомлении необходимо добавить следующий код:

class ViewController: UIViewController {    
    override func viewDidLoad() {
        super.viewDidLoad()                        
        PushNotificationService.subscribeDeeplink(self)
    }
}                
extension ViewController: PushNotificationServiceDelegate {
    func getDeeplink(_ deeplink: String) {
        print(deeplink)
    }
}       

Для начала нужно подписаться на получение deeplink, а далее при отправке push с зашитым значением deeplink будет вызываться метод getDeeplink, который имеет параметр со значением deeplink в виде строки. Чтобы отписаться от получения deeplink добавьте следующий код:

PushNotificationService.unsubscribeDeeplink()    

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

9. Модель пуш-уведомления

Можно получить модель пуш-уведомления, подписавшись на делегат PushNotificationServiceDelegate:

class ViewController: UIViewController {    
    override func viewDidLoad() {
        super.viewDidLoad()                        
        PushNotificationService.subscribeDeeplink(self)
    }
}                
extension ViewController: PushNotificationServiceDelegate {
    func getPushData(_ pushData: PushData) {
        print(pushData)
    }
}    

10. Отписка от пушей

Для возможности отписаться от пушей вызовите метод и передайте в него значение account.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()          
        SessionService.delegate = self
        PushNotificationService.unsubscribePush(account: "account")
    }
}                
extension ViewController: SessionServiceDelegate {
    func sessionCreated() { }
    func sessionStarted() { }
    func pushSubscribed() { }
    func pushUnsubscribed() { }
    func pushClicked() { }
    func tokenRefreshed() { }
    func failure(error: Error) { }    
} 

где account - системное имя вашего аккаунта в enKod (запросите у персонального менеджера)

Методы и условия срабатывания:

  • sessionCreated сессия успешно создана и ID сессии, также как и token, хранятся в UserDefaults
  • sessionStarted сессия с ранее созданным ID успешно началась
  • pushSubscribed подписка на пуш-уведомления успешно завершена
  • pushUnsubscribed отписка на пуш-уведомления успешно завершена
  • pushClicked действие пуш-уведомления успешно отправлено на сервер
  • tokenRefreshed обновился токен и был отправлен на сервер
  • failure в одном из запросов произошла ошибка

Для получения sessionID используйте следующий код:

PushNotificationService.getSessionID

Для получения token используйте следующий код:

PushNotificationService.getToken   

11. Обработка RichPush

Для того чтобы реализовать возможность разворачивания пуш-уведомления с изображением, необходимо добавить таргет Notification Service Extension, в котором необходимо переопределить метод didReceive.

Для работы данного функционала необходимо передавать следующие поля:

"image_url" адрес изображения, по которому будет загружаться отображаемое изображение
"mutable-content" true, для возможности модификации принятого пуша перед его показом

Для динамической обработки кнопок в уведомлении должно содержаться поле «buttons» со следующей структурой:

[{
    "id": "button1",
    "label": "text on button",
    "action": "",???
    "link": "https://somewhere.com" / "https://testApp/mainScreen"
}] 

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

if let buttons = apnsData["buttons"] as? [Any] {
    var acts: Array = []
        for b in buttons{
            let but = b as? NSDictionary
            let id = but?["id"] as! String
            let title = but?["label"] as! String
            let action = UNNotificationAction(identifier: id, title: title, options:
            [.foreground])//.foreground нужен для открытия приложения 
            перед открытием ссылки
        acts.append(action)
    }    
let cat = UNNotificationCategory(identifier: "cat1",
actions: acts, intentIdentifiers: [], options: [])    
    var categories = Set()
    categories.insert(cat)
    UNUserNotificationCenter.current().setNotificationCategories(categories)
}else{
    var categories = Set()
    categories.insert(UNNotificationCategory(identifier: "cat1", 
    actions: [], intentIdentifiers: [], options: []))
    UNUserNotificationCenter.current().setNotificationCategories(categories)
}     

Модель пуш-уведомлений

Модель сообщения

{
    "aps": {
            "alert": {
                "title": "Title",
                "subtitle": "Subtitle",
                "body": "Body"
                },
            "buttons":[
                {
                    "id": "button1",
                    "label": "text on button",
                    "action": "",???
                    "link": "https://somewhere.com"	
                    },
                {
                    "id": "button1",
                    "label": "text on button",
                    "action": "",???
                    "link": "https://somewhere.com"
                    }
            ]
            "sound": "default",
            "badge": 12,
            "category": "CATEGORY",
            "personId": "123",
            "messageId": "321",
            "intent" : "0",
            "url": "https://url.com",
            "mutable-content": 1, 
            "image-url": "https://picture.com"
    }
}  

Значение данных

"alert" информация для отображения уведомлений
"title" заголовок уведомления
"subtitle" подзаголовок уведомления. Дополнительная информация
"body" содержание уведомления
"sound" звук уведомления. Если параметр не передавать, то звука при получения уведомления не будет
"badge" число, отображаемое на значке приложения. Укажите, 0, чтобы удалить текущий значок, если он есть
"category" тип уведомления. Эта строка должна соответствовать identifier одному из объектов, которые вы регистрируете во время запуска
"personId" ID пользователя
"messageId" ID сообщения
"intent" действие, которое будет выполнено по нажатию по пушу. Если «0», то произойдет открытие приложения с передачей туда динамической ссылки для дальнейшей ее обработке, если «1» - открытие ссылки в браузере, если «2» - будет открыто приложения
"url" ссылка динамическая или для открытия в браузере
"mutable-content" флаг, разрешающий изменять содержимое пуша перед его показом. Используется для возможности показывать большое изображение при нажатии (удержании) на пуш (Rich push)
"image-url" ссылка, содержащая адрес изображения в пуше. Применяется для показа большого изображения при нажатии (удержании) на пуш
Последнее изменение: 2023.10.19 06:20 — Anastasia Aniskova