Перевод статьи
Локальные уведомления, Push-уведомления. Триггеры местоположения. Мультимедийные сообщения, дополненные изображениями, видео, гифками или полностью пользовательским пользовательским интерфейсом. Изменения iOS15
Введение
Почти каждому приложению нужен способ общения с пользователями. Одна из основных целей маркетинговой команды — донести до большего числа пользователей актуальную информацию, взаимодействовать с ними и помочь понять ценность приложения. Одним из их любимых вариантов являются push-уведомления.
Когда я начал работать с уведомлениями после пары туториалов, я думал, что знаю все. И с каждым запросом функции я находил что-то новое. Эта статья будет охватывать действительно широкий спектр знаний, основанных на моем опыте.
Прежде чем мы углубимся в детали, вот текстовая игра, над которой я работал давным-давно, в которой активно используются уведомления. Он поддерживается на iPhone, но на Apple Watch можно получить больше удовольствия. Линия жизни: Белая мгла
В этой статье будут рассмотрены несколько тем, таких как:
- Локальные уведомления
- Всплывающие уведомления
- Тихие push-сообщения
- Как добавить кнопки действий
- Как настроить его в Xcode
- Как зарегистрироваться
- Типы сообщений и состояния
- iOS 15 изменения
- APNs
- Как настроить сертификат
- Rich Media (мультимедийные сообщения с изображением, GIF или видео),Расширение службы уведомлений
- Rich Media (сообщения с пользовательским содержимым),Расширение содержания уведомления
- Пример того, как представить MapKit
- Как справиться с подсчетом значков
- Как тестировать на симуляторе и на устройстве
- Полезные инструменты
- Хорошие сторонние сервисы push-уведомлений
Подпишитесь на уведомления
Независимо от того, выбран тип локального или push-уведомления, первым делом нужно попросить пользователя разрешить ему получать уведомления. Зарегистрироваться, чтобы иметь возможность получать уведомления. Много раз он вызывается из приложения (_:didFinishLaunchingWithOptions:), но гораздо более аккуратный вариант — вызывать его из пользовательского экрана, чтобы объяснить пользователю, почему мы будем использовать локальные и/или push-уведомления и их преимущества.
Когда мы вызываем requestAuthorization(options:), ОС представит представление Alert, которое можно увидеть на предыдущем изображении. Красным выделено имя приложения. Зеленая основа — это запрошенные параметры.
На изображении ниже показан один из примеров того, как пользовательский экран объясняет разрешения. Следует отметить, что когда ОС представляет предупреждение, приложение перейдет в фоновый режим, и после того, как пользователь ответит на вопрос разрешения ОС, оно вернется к приложению. Это означает, что он вызовет методы жизненного цикла AppDelegate/SceneDelegate.
Первым шагом является импорт UserNotifications.Далее нужно создать конфигурацию, которую мы хотели бы использовать, например, let options:UNAuthorizationOptions = [.alert, .sound, .badge].
func requestNotificationAuthorization() {
let nc = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
nc.requestAuthorization(options: options) { granted, _ in
print("\(#function) Permission granted: \(granted)")
guard granted else { return }
}
}
Это оповещение, звук и значок будут охватывать большинство потребностей приложения, но есть и другие параметры, такие как carPlay, CriticalAlert или, возможно, предварительные и т. д.
- alert — Чтобы получить всплывающее уведомление,
- sound — чтобы включить звук, по умолчанию используется UNNotificationSound.default.
- badge — Включить использование «красной точки» с номером на значке приложения.
- carPlay — Чтобы иметь возможность отображать уведомления в CarPlay (ссылка на действительно хороший учебник по использованию CarPlay от друга)
- CriticalAlert — предупреждение о критической ситуации проходит через «Не беспокоить». Должен быть разрешен специальным правом Apple.
- предварительный — с этой опцией вам не нужно спрашивать разрешения у пользователя. Вы можете отправлять уведомления прямо сейчас. Но только в Центр уведомлений
Если вы хотите проверить, какие параметры разрешены в приложении для пользователя, вы можете сделать это, используя следующий код:
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Notification settings: \(settings)")
}
}
Предварительные сообщения
Как уже упоминалось, это тихие сообщения, на которые не обращают внимания, и пользователь может получить их при установке приложения. Не нужно спрашивать разрешения. Вам все еще нужно вызвать метод requestAuthorization(options:). Но это не вызовет никаких вопросов у пользователя.
let options: UNAuthorizationOptions = [.provisional]
На предыдущем изображении вы можете увидеть, как пользователь видит сообщение. Пользователь по-прежнему может настроить его в настройках по своему усмотрению.
Локальные уведомления
Этот вид уведомления, как уже говорит нам его название, создается локально, в автономном режиме. Локальные уведомления могут быть запланированы по временному интервалу в качестве напоминания, которое будет запускать их по точному времени дня как событие или по географическому положению, геозоне. Примеры:
- Если вы хотите уведомить пользователя прекратить играть в World of Warcraft и проверить мясо, которое готовилось в течение 20 минут, иначе оно сгорит (интервал времени).
- Что сегодня 1 февраля день рождения твоего лучшего друга (Календарь).
- Что вы проходите мимо любимого магазина и вам нужно за молоком (местоположение)
- Загрузка файла завершена в фоновом режиме (Интервал времени/Мгновенно)
Чтобы создать локальные уведомления, вам нужно запросить у пользователя разрешение, как в предыдущем объяснении.
Когда вы создаете локальное уведомление, ОС берет на себя ответственность. Когда ваше приложение убито или находится в фоновом режиме, ОС позаботится о том, чтобы оно было представлено пользователю при необходимости.
Локальные уведомления — это способ привлечь внимание пользователей и увеличить взаимодействие с приложением.
С технической точки зрения каждое локальное уведомление состоит из трех частей:
Содержание
Это визуальные и конфигурационные свойства уведомления.
- title — Простая строка, заголовок сообщения
- subtitle — Простая строка, подзаголовок сообщения. Обычно это опционально используется маркетинговой командой.
- body — простая строка, подзаголовок сообщения. Содержание сообщения
- sound — UNNotificationSound.default используется по умолчанию. Вы можете использовать пользовательский
- badge — номер на «Красной точке». Вы можете использовать это, чтобы установить точное число. Но вы можете иметь свою собственную систему, которая будет прибавлять или вычитать счет в зависимости от ваших потребностей. Вы можете комбинировать его с вашими входящими сообщениями, какой-либо системой обмена сообщениями для конкретного приложения. Что бы вы ни поддерживали.
- user info — вы можете передать некоторые данные в виде пары ключ:значение.
- attachments — вы можете использовать мультимедийные файлы, хранящиеся в вашем телефоне. По сути, вы можете иметь какое-то видео, изображение или gif в комплекте приложения и использовать его в качестве ресурса. Я не использовал это, так как Rich Media был гораздо лучшим вариантом, поскольку ресурсы загружаются. Позже это будет объяснено.
- categoryIdentifier — это интересный вариант. Вы можете использовать это, чтобы добавить кнопки действий к уведомлению или различать мультимедийные файлы (расширение службы уведомлений или ваши действия расширения содержимого уведомлений).
- interruptionLevel — это привнесла iOS 15. Это сообщает системе, насколько важно сообщение и когда его отправить.
- active — система немедленно представляет уведомление, загорается экран и может воспроизводить звук.
- critical — система немедленно представляет уведомление, включает экран и отключает звук, чтобы воспроизвести звук.
- passive — система добавляет уведомление в список уведомлений без подсветки экрана и воспроизведения звука.
- timeSensitive — система немедленно представляет уведомление, загорается экран и может воспроизводить звук, но не прерывает элементы управления системными уведомлениями.
- threadIdentifier — вы можете назначить каждому локальному или push-уведомлению идентификатор, чтобы сгруппировать их визуально в Центре уведомлений. Например, все информационные сообщения должны быть сгруппированы.
Триггер
Это тип триггера, который разбудит ОС и отправит уведомление.
- time — timeInterval, время, которое пройдет до срабатывания уведомления
- calendar — точная дата-время, когда нужно запустить уведомление
- location — когда вы входите или выходите из определенного региона, срабатывает уведомление.
Запрос
Запрос используется только для того, чтобы сгруппировать все данные сверху. Он имеет содержимое, триггер и идентификатор.
Стоит отметить, что идентификатор важен, если вы хотите отменить уведомление. Мы уже говорили, что вы создаете уведомление в приложении. Но ОС берет верх и дополняет список. Если у вас нет идентификатора, вы не можете попросить ОС отменить его.
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: "my_notification_id")
Ниже приведен пример кода типов уведомлений:
// 1. Create Local Notification and Add Content
let content = UNMutableNotificationContent()
content.title = "Local Notfication Title 🙂"
content.subtitle = "Local Notfication Subtitle"
content.body = "Local Notfication Body"
content.sound = UNNotificationSound.default
content.badge = 1 // You can handle this from BackEnd side, App can have mechanism to
// 2. Create Trigger and Configure the desired behaviour
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, // In 3s will send the Notification
repeats: false) // Will send just Ones
// Choose a random identifier, this is important if you want to be able to cancle the Notification
let notificationIdentifier = UUID().uuidString + "some_uniq_identifier"
// 3. Create the Request
let request = UNNotificationRequest(identifier: notificationIdentifier,
content: content,
trigger: trigger)
// 4. Add our Notification Request to the que
UNUserNotificationCenter.current().add(request)
// 1. Create Local Notification and Add Content
let content = UNMutableNotificationContent()
content.title = "'Title': Local Notification 🙂"
content.subtitle = "'Subtitle': Calendar"
content.body = "'Body': Used 'DateComponents' to trigger it exactly at Time"
content.sound = UNNotificationSound.default
content.badge = 1
content.categoryIdentifier = "myActionCategoryIdentifier"
content.userInfo = ["customDataKey": "cusom_data_value"]
// 2. Create Trigger and Configure the desired behaviour - Calendar
var date = DateComponents()
date.year = 2022
date.month = 1
date.day = 30
date.hour = 15
date.minute = 08
date.second = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)
// Choose a random identifier, this is important if you want to be able to cancle the Notification
notificationIdentifier = UUID().uuidString + "_" + "some_uniq_identifier" // E.g. 123-abc_clock-alarm
let request = UNNotificationRequest(identifier: notificationIdentifier,
content: content,
trigger: trigger)
// 3. Create the Request
UNUserNotificationCenter.current().add(request)
Для типа местоположения локального уведомления я покажу пример, но не буду вдаваться в подробности. Это отдельная история, и я напишу об этом отдельную статью. На высоком уровне вам нужно использовать модуль CoreLocation, чтобы иметь возможность использовать геозону.
Вот код:
// 1. Create Local Notification and Add Content
let content = UNMutableNotificationContent()
content.title = "'Title': Local Notification 🙂"
content.subtitle = "'Subtitle': Location"
content.body = "'Body': Used 'region' to trigger when enter or exit"
content.sound = UNNotificationSound.default
content.badge = 1
content.categoryIdentifier = "myActionMessage"
content.userInfo = ["customDataKey": "cusom_data_value"]
// 2. Create Trigger and Configure the desired behaviour - Location
let location = CLLocationCoordinate2D(latitude: 45.255981,
longitude: 19.844488)
let region = CLCircularRegion(center: location,
radius: 2,
identifier: UUID().uuidString)
let trigger = UNLocationNotificationTrigger(region: region, repeats: false) // Location trigger
// Choose a random identifier, this is important if you want to be able to cancle the Notification
notificationIdentifier = UUID().uuidString + "_" + "some_uniq_identifier" // E.g. 123-abc_clock-alarm
let request = UNNotificationRequest(identifier: notificationIdentifier,
content: content,
trigger: trigger)
// 3. Create the Request
UNUserNotificationCenter.current().add(request)
В разделе Content вы можете увидеть threadIdentifier. Вы можете использовать это для группировки уведомлений. Например, по уникальному пользователю или акции по сделке. До iOS 15 существовало свойство summaryArgument, которое было дополнением к группировке, но теперь оно устарело.
Слушайте события
На данный момент мы импортировали UserNotifications, зарегистрированные с помощью requestAuthorization(options:), но мы все еще не можем прослушивать события.
Следующим шагом является соответствие протоколу UNUserNotificationCenterDelegate. Вы можете сделать это несколькими способами. Я сделал это для простоты в AppDelegate, но вы можете создать отдельный Service/Manager или сделать это во ViewController, все это ситуативно и окончательного пути нет.
Если вы хотите получать уведомления на переднем плане, то в методе userNotificationCenter(_:willPresent:withCompletionHandler:) это можно настроить, смотрите на completeHandler([.alert, .badge, .sound]).
Теперь вы можете прослушивать локальные/push-уведомления с помощью userNotificationCenter(_:didReceive:withCompletionHandler:) и данных userInfo. Если у него есть настраиваемые кнопки действий, я объясню их в следующем разделе.
Если вы хотите создать несколько локальных уведомлений, позаботьтесь о том, чтобы у них не было одного и того же идентификатора, так как новое сообщение переопределит старое с тем же идентификатором. Вот код:
import UserNotifications // 1. Import
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self // 3. Add delegate what enables to fire some events
registerForPushNotifications() // 2. Register
return true
}
}
// MARK: - Notification
extension AppDelegate: UNUserNotificationCenterDelegate { // 4. Make sure to conform to protocol
// MARK: - Receive
// Called when a notification is delivered to a foreground app.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
// Called to let your app know which action was selected by the user for a given notification.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// 1. Get the Notification Identifier
let identifier = response.notification.request.identifier
print("🆔 \(#function) Id: \(identifier)")
// 2. Check for Custom Actions to Handle
switch response.actionIdentifier {
case UNNotificationDefaultActionIdentifier: print("Default Action identifier") // the user swiped to unlock
default: print("Switch default")
}
// 3. Check for Custom data passed with Notification
let userInfo = response.notification.request.content.userInfo
if let customData = userInfo["customDataKey"] as? String {
print("Custom data received: \(customData)")
}
// You must call the completion handler when you're done
completionHandler()
}
}
Действие
Мы можем определить действия/кнопки для уведомлений. Для этого нам нужно определить действия с помощью UNNotificationAction. А затем добавить их в категорию с помощью UNNotificationCategory. Код показан ниже:
let center = UNUserNotificationCenter.current()
// 1. Create Custom Actions
let showMeMoreAction = UNNotificationAction(identifier: "showMeMoreIdentifier",
title: "Show me more",
options: [.foreground])
let snoozeAction = UNNotificationAction(identifier: "snoozeIdentifier",
title: "Snooze",
options: [])
let deleteAction = UNNotificationAction(identifier: "deleteIdentifier",
title: "Delete",
options: [.destructive])
// 2. Register Custom Actions For Category
let category1 = UNNotificationCategory(identifier: "myActionCategoryIdentifier1",
actions: [showMeMoreAction],
intentIdentifiers: [])
let category2 = UNNotificationCategory(identifier: "myActionCategoryIdentifier2",
actions: [snoozeAction, deleteAction],
intentIdentifiers: [])
// 3. Register Categories with OS
center.setNotificationCategories([category1, category2])
Если вы прокрутите назад, когда мы создали уведомления, и добавите следующую строку:
content.categoryIdentifier = "myActionCategoryIdentifier1"
затем он вызовет тип уведомления категории 1. Вы можете видеть, что вы можете создавать множество типов категорий с разным количеством кнопок и функций.
Когда вы получите следующее уведомление и потяните уведомление вниз или нажмите и удерживайте его, вы увидите кнопки действий. Внешний вид кнопок может различаться в разных версиях iOS.
Чтобы определить, какая кнопка нажата пользователем, измените метод userNotificationCenter(_:didReceive:withCompletionHandler:) со следующими строками кода:
// 2. Check for Custom Actions to Handle
switch response.actionIdentifier {
case UNNotificationDefaultActionIdentifier: print("Default Action identifier") // The user swiped to unlock
case UNNotificationDismissActionIdentifier: print("Dismiss Action identifier") // The user dismissed the Notification
case "showMeMoreIdentifier": print("👆 showMeMoreIdentifier")
case "snoozeIdentifier": print("👆 snoozeIdentifier")
case "deleteIdentifier": print("👆 deleteIdentifier")
default: print("Switch default")
}
Например, вы можете отложить повторяющийся будильник, и он снова зазвонит/отправит локальное уведомление через пять минут. Но вы также можете удалить уведомление, что аннулирует это уведомление с идентификатором.
APN (служба push-уведомлений Apple)
На данный момент мы почти готовы к push-уведомлениям. Но прежде чем мы перейдем к этому, нам нужно понять, как зарегистрироваться для получения push-уведомлений. APNs — это служба Apple, которая позволяет нам запрашивать Push-токен.
Состояние разрешения уведомлений
Есть несколько состояний разрешения push-уведомлений. Вы можете использовать это, чтобы решить, должны ли вы представить им предупреждение о разрешении на уведомление или уведомить свою серверную сторону о том, что пользователь отклонил или отключил уведомления.
- notDetermined — у пользователя не запрашиваются разрешения
- Denied — Пользователю выдается предупреждение, но ему отказано.
- authorized — пользователю предоставляется предупреждение, и пользователю разрешено
- provisional — пользователь не запрашивается напрямую, но в коде устанавливается для этого типа разрешения
- ephemeral — приложению разрешено планировать или получать уведомления в течение ограниченного периода времени. Например, AppClip может сделать это с некоторой настройкой в Info.plist. Подробности по следующей ссылке.
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
switch settings.authorizationStatus {
case .notDetermined: print("notDetermined")
case .denied: print("denied")
case .authorized: print("authorized")
case .provisional: print("provisional")
case .ephemeral: print("ephemeral")
default: break
}
})
Всплывающие уведомления
Весь пользовательский интерфейс, который мы видели до сих пор с локальными уведомлениями, можно применять и с push-уведомлениями. Единственное отличие состоит в том, что push-уведомления запускаются удаленно и должны проходить через APN.
Учитывая конфигурацию, сначала нам нужно включить push-уведомления для проекта в Xcode.
Часть регистрации почти такая же, как и с локальным уведомлением. На самом деле, мы будем использовать тот же метод, что и выше, requestAuthorization(options:). Разница в том, что теперь мы также хотим вызвать
UIApplication.shared.registerForRemoteNotifications()
// 1. Create Options
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
// 2. Call Request Authorazion with Options
UNUserNotificationCenter.current().requestAuthorization(options: [options]) { granted, _ in
guard granted else { return }
DispatchQueue.main.async {
// 3. Register For Remote Notifications
UIApplication.shared.registerForRemoteNotifications()
}
}
Это вызовет приложение (_:didRegisterForRemoteNotificationsWithDeviceToken:), и токен будет получен. Или в случае сбоя приложения (_:didFailToRegisterForRemoteNotificationsWithError:).
Токен выглядит примерно так: 9340516ea8a5ae6b149fa90c07efc1f738b2b0d38463cd326858921fc0d93a91
Поскольку APN являются центральной точкой, откуда мы получаем токен удаленного уведомления, иногда брандмауэры не хотят пропускать. Особенно в случае с беспроводной связью. По крайней мере, это мой опыт и предположение. Может помочь сброс Wi-Fi, роутера или переключение на сотовую связь.Кроме того, имейте в виду, что это асинхронный процесс. Получение токена может занять некоторое время — секунды, а иногда и минуты.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { data in String(format: "%02.2hhx", data) }.joined()
print("🆔 \(#function) Token: \(token)")
}
Мы должны отправить этот токен на наш сервер или в стороннюю службу, которую мы или маркетинговая команда будем использовать для создания push-сообщений.
Существует множество таких сторонних сервисов, таких как LeanPlum, CleverTap, OneSignal, FirebaseCloud Messaging, UrbanAirship и т. д. Это может значительно упростить интеграцию.
Тестирование push-уведомлений
Если вы используете симулятор, не волнуйтесь. Есть способ сделать это.
Во-первых, вам нужен файл с расширением .apns. Что-то вроде payload.apns. Он имеет структуру, подобную JSON.
{
"Simulator Target Bundle": "com.example.yourAppBudle",
"aps" : {
"alert" : {
"title" : "Simple title",
"body" : "Simple body"
}
}
}
Вам нужно изменить значение целевого пакета симулятора в файле apns на идентификатор пакета вашего приложения. На следующем изображении показано, как его найти.
Наиболее часто используемые свойства файла apns:
- alert— заголовок, подзаголовок, тело, которое говорит само за себя
- badge— количество красных точек.
- sound — строка «по умолчанию» для воспроизведения звука по умолчанию или «my_sound.mp3» из пакета.
- category — это строка, которая будет определять идентификатор категории кнопок действий из локальной части уведомлений.
- thread-id — это идентификатор, который используется для группировки сообщений.
- Content-Available — это флаг фонового уведомления. «Чтобы выполнить фоновое обновление без вывода сообщений, укажите значение 1 и не включайте оповещения, значки или звуковые клавиши в свою полезную нагрузку». — Яблоко
- mutable-content — если это значение равно 1, это означает, что используется расширение приложения-службы. Позже я расскажу об этом подробнее.
- interruption level — это появилось с появлением iOS 15. Строковые значения «passive», «active», «time-sensitive» или «critical».
Подробный список можно найти по этой ссылке.
{
"aps" : {
"badge" : 9,
"sound" : "my_sound.mp3",
"alert" : {
"title" : "Simple Push Notification Title",
"subtitle" : "Simple Push Notification Subtitle",
"body" : "Simple Push Notification Body"
},
"category" : "myActionCategoryIdentifier1"
},
"customKey" : "12345678"
}
Еще один способ — протестировать push-уведомления из Терминала.
$ xcrun simctl push device_identifier com.example.yourApp payload.apns
Вам нужно заменить device_identifier. Вы можете увидеть, как найти это значение, на следующем изображении.
Если в полезной нагрузке у вас есть «Simulator Target Bundle», то вводить команду не нужно. Если вы правильно настроили команду, то на терминале появится что-то вроде «Уведомление отправлено на «com.example.myApp».
Тихие push-уведомления
Тихие push-уведомления — это сообщения без предупреждений, пользовательского интерфейса и звука, которые можно получать в фоновом режиме. Чтобы иметь возможность использовать тихие push-уведомления, недостаточно настроить полезную нагрузку с «mutable-content»: 1 . Нам также необходимо настроить приложение. Нам нужно включить фоновые режимы для удаленных уведомлений.
Тихие push-уведомления не могут содержать alert, title, body или звук и т. д.
{
"aps" : {
"content-available" : 1
},
"customKey1" : "value1",
"customKey2" : 42
}
Тихие push-уведомления с практической точки зрения используются для инициирования некоторых вызовов API фоновой выборки, для запуска некоторых обновлений, для возможности выполнения задачи в фоновом режиме и т. д. Это пробуждает приложение из фона.
Количество значков
Вы можете установить значок с номером на значке приложения, чтобы пользователь знал, что ему необходимо внимание. Что в приложении есть что-то новое.
Если у вас нет кастомного механизма, то проще всего его сбросить. Чтобы сделать это в событии AppDelegate applicationDidBecomeActive(_:) (или sceneDidBecomeActive(_:) в случае SceneDelegate), вызовите следующую строку кода:
UIApplication.shared.applicationIconBadgeNumber = 0
Rich Media (мультимедийное уведомление)
Это самая веселая часть. Мы можем использовать изображение, видео, gif или создать собственный UIView.
Push-уведомления имеют максимальный размер полезной нагрузки 4 КБ. С расширениями у нас есть возможность перехватить любое входящее push-уведомление и изменить заголовок, расшифровав любые зашифрованные данные или даже загрузив мультимедийные вложения.
Если вы не знакомы с расширениями, они похожи на мини-приложения, которые каким-то образом связаны с вашим основным приложением, объединенным внутри. Они являются «привратниками» вашего приложения. В случае с push-уведомлением у них есть возможность выполнить какое-либо действие до того, как ваше приложение получит push-уведомление.
{
"aps": {
"alert": {
"title": "Rich Media Push Notification Title",
"body": "Rich Media Push Notification Body"
},
"mutable-content": 1
},
"media-url": "https://some_image.jpg"
}
Как вы видите, «mutable-content»: 1 означает, что это мультимедийное push-уведомление.
Расширение службы уведомлений
В начале статьи вы могли видеть push-уведомление Rich Media с расширением видео (mp4). Ниже вы можете увидеть один с фото:
В нашем случае у Service Extension есть шанс загрузить какое-то изображение, видео или gif, в зависимости от того, какой URL находится в полезной нагрузке. Например, ОС дает сервисному расширению некоторое время, чтобы изменить заголовок, тело или, возможно, загрузить изображение. Если вы не можете изменить контент, он вернется к обычным push-уведомлениям с исходным контентом из полезной нагрузки.
Чтобы добавить в проект расширение службы уведомлений, перейдите в меню -> Файл -> Создать -> Цель. Выберите Расширение службы уведомлений и нажмите кнопку Далее.
Посмотрите на идентификатор организации и bundle идентификатор. Идентификатор расширения основан на идентификаторе вашего основного целевого пакета приложения, разница заключается в постфиксе. Таким образом, iOS знает, в какое приложение встроено расширение.
С помощью метода didReceive(_ request:) мы можем перехватывать и изменять содержимое.serviceExtensionTimeWillExpire() — это запасной вариант на случай, если мы не сможем изменить содержимое. Например, если загрузка образа не удалась или заняла слишком много времени.
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// 1. Try to Modify the notification content here...
bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// 2. Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Полный код можно найти по следующей ссылке.
{
"aps": {
"alert": {
"title": "Teamwork Makes Dream Work ",
"body": "Rich Media Video"
},
"mutable-content": 1,
"category": "myMediaServiceCategory"
},
"media-url": "https://sample_video.mp4"
}
Вы можете видеть, что Rich Media также может иметь кнопки действий. Вам необходимо зарегистрировать их в Service Extension. Но обработка крана должна выполняться в приложении. В нашем случае в AppDelegate.
let likeAction = UNNotificationAction(identifier: "likeIdentifier",
title: "Like ❤️",
options: [])
let saveAction = UNNotificationAction(identifier: "shareIdentifier",
title: "Share ⬆️",
options: [])
let category = UNNotificationCategory(identifier: "myMediaCategory",
actions: [likeAction, saveAction],
intentIdentifiers: [],
options: [])
UNUserNotificationCenter.current().setNotificationCategories([category])
Расширение содержания уведомления
Content Extension — это создание пользовательского представления. Расширение содержимого уведомлений использует NotificationViewController, который является подклассом UIViewController. Так же создает в папке раскадровку и Info.plist.Настройка аналогична сервисному расширению. Просто выполните предыдущие шаги.
Ниже вы можете увидеть действительно хороший пользовательский вид — карусель с несколькими изображениями, заголовками, субтитрами и кнопками. Каждое изображение может иметь свой текст. У каждого изображения может быть своя Deep-ссылка.
Чтобы иметь возможность использовать Content Extension в Info.plist, найдите UNNotificationExtensionCategory и его значение, которое необходимо добавить в полезные данные push-уведомления под ключом «category».
Этот тип уведомления может даже иметь интегрированные карты или любую структуру.Конечно, держите его легким.
Теперь возможности практически безграничны.
Сертификаты
Я попытаюсь объяснить это просто и сосредоточусь на Push-сертификатах.Перейдите на https://developer.apple.com/account/ Сертификаты, идентификаторы и профили.
- Нажмите на знак «+», сервис push-уведомлений Apple SSL.
- Выберите идентификатор приложения (предположим, вы его создали)
- Загрузите файл aps_xyz.cer.
- Дважды щелкните его, перейдите в Keychain Access.app (cmd + пробел открывает Spotlight и введите Keyc…)
- Вы должны увидеть Apple Sandbox Push Services: com.example.demo (ваш идентификатор пакета)
- Щелкните правой кнопкой мыши
- Экспорт «Яблочная песочница…»
- Сохраните файл .p12.
Серверная часть в основном будет запрашивать этот файл .p12, чтобы иметь возможность отправлять push-уведомления через APN. Но лучше создать файл ключа /.p8.
Совет
Срок действия push-сертификатов истекает через год, и вы должны обновлять их в центре разработчиков Apple и каждый год повторно загружать новый сертификат в ваш push-провайдер/серверную часть. Если у вас больше приложений, этот процесс необходимо выполнять каждый год для каждого приложения. Файл p8/key работает со всеми вашими приложениями как в среде разработки, так и в рабочей среде, и срок его действия не истекает.
Инструменты
Вот инструменты, которые можно легко протестировать на устройстве:
https://github.com/onmyway133/PushNotifications 👈 Моя рекомендация
Заключение
Теперь вы знаете, что делать с уведомлениями пользователей, как их называет Apple. Как я уже сказал, мне понадобились годы и годы, чтобы собрать всю информацию и изучить ее. Пожалуйста, не стесняйтесь рассказать мне что-то, что может меня заинтересовать, но я не знаю.
Если вы дошли до этого места, спасибо за чтение. Вы заслуживаете кофе ☕️. 🙂 Если вам понравился контент пожалуйста 👏, поделитесь, подпишитесь, это значит для меня. Если у вас есть предложения или вопросы, пожалуйста, не стесняйтесь комментировать.