Перейти к основному содержимому
Документация для версии v73

Конфигурация mSDK

Предварительные условия

  • SDK провайдеров push-уведомлений интегрированы в проект приложения (см. инструкции по интеграции push-провайдеров).
  • Выполнена загрузка пакета Altcraft с помощью Swift Package Manager.

Подготовка приложения

Настройка таргета

Настройте следующие параметры таргета приложения:

  • General:

    • Проверьте, что библиотека Altcraft добавлена в Frameworks, Libraries, and Embedded Content таргета приложения.
  • Signing & Capabilities:

    • PushNotifications;
    • AppGroups — укажите идентификатор для группы (добавление идентификатора App Group необходимо обмена информацией с Notification Service Extension);
    • Background Modes — выберите Background fetch, Background processing.
  • Info:

    • Добавьте ключ Permitted background task scheduler identifiers и значение "lib.Altcraft.bgTask.systemControl" для этого ключа. Это необходимо для регистрации bgTask-задачи, которая будет выполнять повтор неудачных запросов к серверу в background-режиме.
      опционально — при использовании Firebase Cloud Messaging добавьте ключ FirebaseAppDelegateProxyEnabled (Boolean) с значением NO. Это отключит автоматическую подмену (method swizzling) методов AppDelegate, которую Firebase Messaging выполняет по умолчанию.

Настройка AppDelegate

Далее необходимо выполнить в AppDelegate.application(_:didFinishLaunchingWithOptions:) следующие действия:

  • передать идентификатор AppGroup в SDK
  • зарегистрировать BGTask (фоновые задачи SDK)
  • (опционально) инициализировать функции UNUserNotificationCenter на стороне SDK

Установка идентификатора AppGroup

Добавление идентификатора AppGroup необходимо для обмена информацией с Notification Service Extension и требуется для корректной работы SDK. Выполняется с помощью функции setAppGroup():

// App Group setup and Core Data initialization for the shared container
AltcraftSDK.shared.setAppGroup(groupName: String)

Регистрация BGTask

Регистрация фоновых задач SDK необходима для повторной отправки неуспешных запросов в фоновом режиме. Выпоняется с помощью функции registerBackgroundTask():

// Register a background SDK task and schedule periodic runs (every ~3 hours)
AltcraftSDK.shared.backgroundTasks.registerBackgroundTask()

Инициализация функций UNUserNotificationCenter (опционально)

SDK содержит класс NotificationManager который выполняет следующие задачи:

  • настраивает UNUserNotificationCenter и запрашивает разрешение на уведомление (alert/sound/badge);
  • обеспечивает вызов UIApplication.registerForRemoteNotifications() и гарантирует корректную регистрацию в APNs;
  • отображает уведомления в foreground;
  • обрабатывает клики по уведомлениям и кнопкам — выполняет переход на указанный URL или открывает приложение;
  • регистрирует push-событие открытия ("open").

Для использования класса SDK NotificationManager вызовите функцию в AppDelegate.application(_:didFinishLaunchingWithOptions:):

func registerForPushNotifications(for application: UIApplication, completion: ((_ granted: Bool, _ error: Error?) -> Void)? = nil): Void

Данная функция назначает делегата, запрашивает разрешение у пользователя и регистрирует приложение для получения push-уведомлений на стороне SDK.

Пример корректного заполнения AppDelegate.application
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let appGroup = "group.your.name.example"

//App Group identifier setup
AltcraftSDK.shared.setAppGroup(groupName: appGroup)

//SDK background task registration
AltcraftSDK.shared.backgroundTasks.registerBackgroundTask()

//SDK UNUserNotificationCenter functions initialization
AltcraftSDK.shared.notificationManager.registerForPushNotifications(for: application)

//Other functions

return true
}
//Other functions AppDelegate
}

Использование этого класса опционально, вы можете заменить его своей реализацией. Для этого:

  • назначьте делегата центра уведомлений:
    UNUserNotificationCenter.current().delegate = self;
  • запросите разрешения на уведомления и вызовите UIApplication.shared.registerForRemoteNotifications() строго на главном потоке;
  • реализуйте метод userNotificationCenter(_:willPresent:withCompletionHandler:) для отображения уведомлений в foreground (banner/alert/sound/badge);
  • вызовите AltcraftSDK.shared.pushEventFunctions.openEvent(from:) в userNotificationCenter(_:didReceive:withCompletionHandler:) при обработке нажатия на уведомление (регистрация события "open");
  • реализуйте собственную логику обработки кликов по уведомлению (URL/Deep Link/кнопки), не забудьте при этом продумать fallback-сценарий (навигацию по умолчанию при отсутствии валидной ссылки).

Настройка JWT-протокола (опционально)

JWTInterface — протокол запроса JWT-токена. Предоставляет актуальный JWT-токен из приложения по запросу SDK. Реализация данного протокола требуется, если используется JWT-аутентификация API-запросов. JWT подтверждает, что пользовательские идентификаторы аутентифицированы приложением.

Реализация JWT-аутентификации обязательна, если используется тип матчинга отличный от push-данных из подписки (например, идентификатор пользователя — email или телефон).

Протокол SDK:

public protocol JWTInterface {
func getToken() -> String?
}
Реализация на стороне приложения
import Altcraft

class JWTProvider: JWTInterface {
func getToken() -> String? {
//your code that returns JWT
}
}
Регистрация провайдера в application(_:didFinishLaunchingWithOptions:)

В AppDelegate укажите:


class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Other code

AltcraftSDK.setJWTProvider(provider: JWTProvider())
}
//Other functions
}
К сведению

getJWT() — синхронная функция. Поток выполнения SDK будет приостановлен до получения JWT. Рекомендуется, чтобы getJWT() возвращал значение немедленно — из кэша (in-memory, SharedPreferences или EncryptedSharedPreferences) — это ускорит выполнение запросов. Желательно подготовить актуальный JWT как можно раньше (на старте приложения) и сохранить его в кэш, чтобы при обращении SDK токен был доступен без задержек. При отсутствии значения допустимо вернуть nil.

Протоколы запроса и удаления push-токена провайдера

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

Регистрируйте провайдеры в application(_:didFinishLaunchingWithOptions:) (AppDelegate). Данная точка регистрации гарантирует раннюю, однократную и детерминированную регистрацию при старте процесса, в том числе в background.


Apple Push Notifcation service

APNSInterface — протокол запроса push-токена APNs. В данном протоколе отсутствует функция удаления токена, в отличии от других протоколов push-провайдеров.

Протокол SDK:

public protocol APNSInterface {

func getToken(completion: @escaping (String?) -> Void)
}
Рекомендуемая реализация на стороне приложения
import Altcraft

class APNSProvider: APNSInterface {
func getToken(completion: @escaping (String?) -> Void) {
//your code that returns APNs token
}
}
Регистрация провайдера в application(_:didFinishLaunchingWithOptions:)
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//other code

AltcraftSDK.pushTokenFunction.setAPNSTokenProvider(APNSProvider())
}
//other functions
}

Firebase Cloud Messaging

FCMInterface — протокол запроса и удаления push-токена Firebase Cloud Messaging.

Протокол SDK:

public protocol FCMInterface {
func getToken(completion: @escaping (String?) -> Void)

func deleteToken(completion: @escaping (Bool) -> Void)
}
Обратите внимание
Рекомендуемая реализация на стороне приложения
import FirebaseMessaging
import Altcraft

class FCMProvider: FCMInterface {

/// Retrieves the current FCM token.
func getToken(completion: @escaping (String?) -> Void) {

///APNs token (as Data) retrieved from userDefault
let apnsToken = getAPNsTokenDataFromUserDefaults()

///set the APNs token for fcm before requesting the fcm token
Messaging.messaging().apnsToken = apnsToken

///fcm token request function
Messaging.messaging().token { token, error in
if error != nil {
completion(nil)
} else {
completion(token)
}
}
}

/// Deletes the current FCM token.
func deleteToken(completion: @escaping (Bool) -> Void) {
Messaging.messaging().deleteToken { error in
if error != nil {
completion(false)
} else {
completion(true)
}
}
}
}
Регистрация провайдера в application(_:didFinishLaunchingWithOptions:)
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Other code

AltcraftSDK.pushTokenFunction.setFCMTokenProvider(FCMProvider())
}
//Other functions
}

Huawei Mobile Services

HMSInterface — протокол запроса и удаления push-токена Huawei Mobile Services.

Протокол SDK:

public protocol HMSInterface {

func getToken(completion: @escaping (String?) -> Void)

func deleteToken(completion: @escaping (Bool) -> Void)
}
Рекомендуемая реализация на стороне приложения
class HMSProvider: HMSInterface {

func getToken(completion: @escaping (String?) -> Void) {

//a variable containing the APNs token (as String) which will later
//passes to HmsInstanceId.getInstance().getToken(apnsToken)
guard let apnsToken = getAPNsTokenFromUserDefault() else {
completion(nil)
return
}


let token = HmsInstanceId.getInstance().getToken(apnsToken)
completion(token)
}


func deleteToken(completion: @escaping (Bool) -> Void) {
HmsInstanceId.getInstance().deleteToken()
completion(true)
}
}
Регистрация провайдера в application(_:didFinishLaunchingWithOptions:)
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Other code

AltcraftSDK.pushTokenFunction.setHMSTokenProvider(HMSProvider())
}
//Other functions
}

Подготовка Notification Service Extension

Добавление расширения NSE необходимо для поддержки Rich Push и гарантированной регистрации событий доставки.

Создайте расширение приложения Notification Service Extension:

  • Выполните FileNewTargetNotification Service Extension;
  • Выберите название (Product Name) для таргета расширения;
  • Активируйте его.

Выполните в Notification Service Extension:

  • General:
    • Укажите Minimum Deployments — это параметр сборки в Xcode, который определяет минимальную версию операционной системы, на которой будет работать Notification Service Extension;
    • Добавьте библиотеку Altcraft в разделе Frameworks, Libraries and Embedded Content.
  • Signing & Capabilities:
    • AppGroups — укажите идентификатор AppGroup.

Затем настройте SDK в UNNotificationServiceExtension:

  • Импортируйте библиотеку Altcraft;
  • Создайте экземпляр AltcraftPushReceiver();
  • В функции didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void):
    • Передайте идентификатор appGroup в функцию AltcraftSDK.shared.setAppGroup(groupName: appGroupsName). Данный идентификатор должен соответствовать идентификатору переданному в SDK в таргете приложения;
    • Установите провайдер JWT (если используется JWT-аутентификация запросов): AltcraftSDK.shared.setJWTProvider(provider: jwtProvider);
    • Выполните проверку источника уведомления с помощью функции isAltcraftPush(request) класса AltcraftPushReceiver(): service.isAltcraftPush(request);
    • После проверки источника уведомления, передайте UNNotificationRequest и contentHandler в функцию didReceive класса AltcraftPushReceiver(): self.service.didReceive(request, withContentHandler: contentHandler), если источник уведомления — Altcraft.

Приведенный ниже пример реализации UNNotificationServiceExtension можно использовать как готовый класс. Замените весь автоматически сгенерированный код на эту реализацию, если вам не требуется дополнительная логика. Если вы уже используете UNNotificationServiceExtension, интегрируйте функции Altcraft в свою реализацию.

Пример реализации UNNotificationServiceExtension
import Altcraft
import UserNotifications

class NotificationService: UNNotificationServiceExtension {
var service = AltcraftPushReceiver()

/// - important! Set app groups name.
var appGroupsName = "your.app.group"
let jwtProvider = JWTProvider()

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {

AltcraftSDK.shared.setAppGroup(groupName: appGroupsName)
AltcraftSDK.shared.setJWTProvider(provider: jwtProvider)

if service.isAltcraftPush(request) {
self.service.didReceive(request, withContentHandler: contentHandler)
} else {
contentHandler(request.content)
}
}
override func serviceExtensionTimeWillExpire() {service.serviceExtensionTimeWillExpire()}
}
Обратите внимание

Таргет приложения и таргет Notification Service Extension работают в отдельных процессах и не разделяют общие объекты. Поэтому для корректной обработки уведомлений SDK необходимо зарегистрировать JWTProvider также в расширении NSE — например, в методе didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void). Это обеспечивает доступ SDK к токену авторизации при отправке push-события доставки ("delivery_event").

Инициализация SDK

Параметры инициализации

Для передачи параметров конфигурации испоользуется класс AltcraftConfiguration:

public final class AltcraftConfiguration {
private let apiUrl: String
private let rToken: String?
private var appInfo: AppInfo?
private var providerPriorityList: [String]?
}

Сборка файла конфигурации происходит после вызова функции build() класса AltcraftConfiguration.Builder(): AltcraftConfiguration.Builder().build().

Описание параметров:

apiUrl String

Обязательный: Да
Описание: URL конечной точки Altcraft API


rToken String?

По умолчанию: nil
Обязательный: Нет
Описание: Ролевой токен Altcraft (идентифицирует ресурс, БД или аккаунт). Используется, если единственный тип матчинга — push-токен устройства, выданный провайдером.


appInfo AppInfo?

По умолчанию: nil
Обязательный: Нет
Описание: Базовые метаданные приложения для Firebase Analytics. Для установки значения этого параметра используйте публичную структуру SDK AppInfo:

public struct AppInfo: Codable {

/// Unique App ID (Firebase `app_id`)
public var appID: String

/// Unique app instance ID (Firebase `app_instance_id`)
public var appIID: String

/// App version (Firebase `app_version`)
public var appVer: String
}

providerPriorityList [String]?

По умолчанию: nil
Обязательный: Нет
Описание: Список приоритетов провайдеров. Используется для автоматического обновления push-токена подписки, если токен более приоритетного провайдера недоступен. Приоритет определяется индексом в списке: элемент с индексом 0 — самый приоритетный.

Пример использования:

providerPriorityList = [
Constants.ProviderName.apns,
Constants.ProviderName.firebase,
Constants.ProviderName.huawei
]

При такой настройке:

  • SDK сначала запросит токен APNs; если APNs недоступен — FCM; если FCM недоступен — HMS;
  • Работает при условии, если в приложении реализованы протоколы соответствующих провайдеров.

Для удобства установки значения параметра SDK содержит публичные константы. Все константы находятся в enum Constants:

public enum Constants {
public enum ProviderName {
/// The provider name for Firebase.
public static let firebase = "ios-firebase"

/// The provider name for APNs.
public static let apns = "ios-apns"

/// The provider name for HMS.
public static let huawei = "ios-huawei"
}
}

Если значение не задано, приоритет провайдеров следующий:

apns → firebase → huawei

Значение параметра может содержать один элемент — в этом случае будет использоваться только один провайдер, независимо от доступности push-токена.

Параметр можно не указывать, если:

  • в проекте используется только один провайдер;
  • приоритет по умолчанию соответствует требованиям.

Выполнение инициализации

Обратите внимание

Вызывайте AltcraftSDK.shared.initialization() тогда, когда это необходимо, но только после установки идентификатора AppGroup и провайдеров, реализующих протоколы SDK. Запросы следует выполнять после установки конфигурации.

Для инициализации SDK используется функция public func initialization(configuration: AltcraftConfiguration?, completion: ((Bool) -> Void)? = nil):

// SDK initialization and configuration setup
AltcraftSDK.shared.initialization(configuration: AltcraftConfiguration?, completion: ((Bool) -> Void)? = nil)

Функция initialization(configuration: AltcraftConfiguration?, completion: ((Bool) -> Void)? = nil) ожидает файл конфигурации AltcraftConfiguration, для которого установлены необходимые значения и выполнена сборка:

 let config = AltcraftConfiguration.Builder()
.setApiUrl("your apiUrl")
.setRToken("your rToken")
.setAppInfo(AppInfo(appID: "your appID", appIID: "your appIID", appVer: "your appVer"))
.setProviderPriorityList([Constants.ProviderName.firebase])
.build()
Пример правильного порядка инициализации SDK в AppDelegate.application(_:didFinishLaunchingWithOptions:) (после установки идентификатора AppGroup и регистрации провайдеров)
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
//здесь может быть инициализация конфигурации firebase если firebase используется в проекте

let appGroup = "group.altcraft.apns.example"

AltcraftSDK.shared.setAppGroup(groupName: appGroup)
AltcraftSDK.shared.backgroundTasks.registerBackgroundTask()
AltcraftSDK.shared.setJWTProvider(provider: JWTProvider())
AltcraftSDK.shared.pushTokenFunction.setAPNSTokenProvider(APNSProvider())
AltcraftSDK.shared.pushTokenFunction.setFCMTokenProvider(FCMProvider())
AltcraftSDK.shared.pushTokenFunction.setHMSTokenProvider(HMSProvider())
AltcraftSDK.shared.notificationManager.registerForPushNotifications(for: application)

let config = AltcraftConfiguration.Builder()
.setApiUrl("your apiUrl")
.setRToken("your rToken")
.setAppInfo(AppInfo(appID: "your appID", appIID: "your appIID", appVer: "your appVer"))
.setProviderPriorityList([Constants.ProviderName.firebase])
.build()

AltcraftSDK.shared.initialization(configuration: config) { success in
if success {
//actions after successfull initialization
}
}

//Остальные функции

return true
}
//Other AppDelegate functions
}