iOS 15 Notifications

通知摘要

通知摘要是一項(xiàng)可選功能,允許用戶停止接收特定應(yīng)用程序的實(shí)時(shí)推送通知。相反,系統(tǒng)會存儲為這些應(yīng)用程序收到的通知,并在鎖屏上的摘要中顯示它們。系統(tǒng)可以在一天中的不同時(shí)刻顯示這些摘要,具體取決于用戶的偏好。

iOS 不會自動將應(yīng)用程序添加到通知摘要中。首次啟用該功能時(shí),用戶需要從系統(tǒng)設(shè)置中手動添加:

image

打開通知摘要后,推送權(quán)限提示將提供兩個選項(xiàng)來處理應(yīng)用程序的通知:

  • Allow Immediate Notifications”:收到通知后立即顯示。

  • Add to Scheduled Summary”:收到通知后稍后顯示在通知摘要中。

image

請注意,iOS 不提供檢測用戶選擇的哪種通知處理方式(立即通知與預(yù)定摘要)。

新增 API

  • relevanceScore 指定應(yīng)在此摘要中突出顯示哪些通知。

專注模式

iOS 15 的新專注模式是當(dāng)前勿擾模式的改進(jìn)和擴(kuò)展。用戶可以創(chuàng)建不同的“專注模式”來過濾他們在活動期間(如:工作、駕駛等)收到的通知。從系統(tǒng)設(shè)置中,用戶可以創(chuàng)建“工作”焦點(diǎn)并將其設(shè)置在同事、家人和特定應(yīng)用程序通知到達(dá)時(shí)立即通知。

image

專注模式激活時(shí),其他聯(lián)系人和應(yīng)用程序的通知將僅顯示在通知中心,如下所示:

image

相關(guān) API

新的通知中斷級別

除了新的通知摘要和專注模式之外,iOS 15 還為推送通知引入了兩個新的中斷級別:passivetime-sensitive。

總共有四個不同的中斷級別:

  • Passive 被動:對不需要立即關(guān)注的通知使用被動模式(如:營銷活動等)。被動通知不會觸發(fā)聲音、振動和亮屏。

  • Active 活動:這是默認(rèn)的中斷級別(如:新聞等)。

  • Time-Sensitive 時(shí)間敏感:對需要立即關(guān)注的通知(如:帳戶安全問題、快遞送達(dá)等)使用時(shí)間敏感中斷級別。該中斷級別不要用于發(fā)送營銷通知,因?yàn)檫@些通知可能會突破系統(tǒng)控制(通知摘要和專注模式)。

  • Critical 嚴(yán)重:嚴(yán)重中斷級別用于需要立即關(guān)注的非常重要的通知(如:惡劣天氣等)。這種使用必須由 Apple 明確允許并具有特殊權(quán)利。

image

請注意,時(shí)間敏感嚴(yán)重中斷級別都可以突破通知摘要任何專注模式。iOS 將顯示剛剛收到的通知:

image

如果 App 的時(shí)間敏感通知不經(jīng)常交互,iOS 會從鎖定屏幕提示用戶,讓用戶為 App 禁用時(shí)間敏感的通知。用戶也可以從系統(tǒng)設(shè)置中禁用:

image

發(fā)送時(shí)間敏感的通知

先決條件

為了使用時(shí)間敏感通知,App 需要將“時(shí)間敏感通知”功能添加到 Xcode 項(xiàng)目中。

image

設(shè)置推送通知數(shù)據(jù)

時(shí)間敏感的中斷級別可以使用“interruption-level” payload key:

{"aps":{"interruption-level":"time-sensitive"}}

新增 API

通知操作圖標(biāo)

通知操作現(xiàn)在可以包含圖標(biāo)以更好的表達(dá)相關(guān)操作。這些圖標(biāo)可以是 SFSymbol 系統(tǒng)圖像,也可以是 App 提供的自定義圖像。為了添加圖標(biāo),Apple 提供了新的 API UNNotificationActionIcon 對象。Action Icon 對象可以使用系統(tǒng)或模板圖像名稱進(jìn)行初始化,然后使用包含 icon 參數(shù)的新初始化方法添加到相應(yīng)的 UNNotificationAction 中。您不需要在名稱中指定文件擴(kuò)展名或大小修飾符,因?yàn)闀鶕?jù)系統(tǒng)和可用圖像資源自動檢索正確的大小。

image
image

通訊通知

Apple 添加了將應(yīng)用程序的通知區(qū)分為通信通知的功能。這些通知現(xiàn)在將包含發(fā)送它們的聯(lián)系人的圖像或頭像,并且可以與 SiriKit 集成,以便 Siri 可以根據(jù)常用聯(lián)系人智能地為通信操作提供快捷方式和建議。例如,當(dāng)用戶為焦點(diǎn)模式設(shè)置允許的聯(lián)系人或從您的應(yīng)用撥打電話時(shí)。 Siri 將根據(jù)您的應(yīng)用程序提供的意圖數(shù)據(jù)智能地推薦聯(lián)系人。

要使用通信通知,應(yīng)用程序需要在 Xcode 中向其應(yīng)用程序添加 Communication Notifications 功能,并使用實(shí)現(xiàn)了 UNNotificationContentProviding 協(xié)議的 Intent 對象更新 App Notification Service Extension 的通知內(nèi)容。目前兩個可用的實(shí)現(xiàn)是 INSendMessageIntentINStartCallIntent。

image

APNs 實(shí)現(xiàn)通訊通知

項(xiàng)目中添加 Notification Service Extension,將以下 key value 添加到 Notification Service Extension 的 Info.plist 中。

image

NotificationService.didReceive 中編寫代碼向通知對象添加附加信息。(每次 Apple APNs 在通知用戶前,都會調(diào)用此方法)

import UserNotifications
import Intents
import UIKit
class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        if let bestAttemptContent = bestAttemptContent {
            // ...
        }
    }
}

需要使用 INPerson 裝載發(fā)送者信息,這些信息可以通過 APNs 通知傳給 App。如:

{
    "aps": {
        "alert": {
            "body": "Hello world! This is a test message.",
            "title": "@Neko"
        },
    },
    "sender_id": "1",
    "sender_name": "NekoNeko",
    "sender_image_url": "https://xxxx.com/xxx.jpg",
    "sender_nickname": "@Neko",
    "sender_email": "Neko@Neko.Neko",
    "chat_session_id": "chat_1"
} 

然后,可以通過使用 INPersonINSendMessageIntent 將發(fā)送者信息添加到推送通知中。

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 {
            // Modify the notification content here...
            bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"

            /* Use the custom information included in this notification from the chat server to retrive the chat participant's information. - This is the information of the sender of the message. - Providing a user's accruate name helps the iOS system match this user with a contact in the system contact app. */
            if let senderAccountID = bestAttemptContent.userInfo["sender_id"] as? String,
               let senderName = bestAttemptContent.userInfo["sender_name"] as? String,
               let senderImageURLString = bestAttemptContent.userInfo["sender_image_url"] as? String,
               let senderImageURL = URL(string: senderImageURLString),
               let senderDisplayName = bestAttemptContent.userInfo["sender_nickname"] as? String,
               let senderEmailAddr = bestAttemptContent.userInfo["sender_email"] as? String,
               let chatSessionID = bestAttemptContent.userInfo["chat_session_id"] as? String
            {

                // You can also use the sender's phone number to initialize the `INPersonHandle` object. This will help the iOS system to match this sender with a contact.
                // TODO: - Here you need to download the image data from the URL. In this demo, we are using a system image instead.
                let messageSender = INPerson(
                    // email or phone number
                    personHandle: INPersonHandle(value: senderEmailAddr, type: .emailAddress),
                    nameComponents: try? PersonNameComponents(senderName),
                    displayName: senderDisplayName,
                    image: INImage(imageData: UIImage(systemName: "applelogo")!.pngData()!),
                    contactIdentifier: nil,
                    customIdentifier: senderAccountID,
                    isMe: false,
                    suggestionType: .instantMessageAddress
                )

                let intent = INSendMessageIntent(recipients: nil,
                                                 outgoingMessageType: .outgoingMessageText,
                                                 content: bestAttemptContent.body,
                                                 speakableGroupName: INSpeakableString(spokenPhrase: senderDisplayName),
                                                 conversationIdentifier: chatSessionID,
                                                 serviceName: nil,
                                                 sender: messageSender,
                                                 attachments: nil)

                let interaction = INInteraction(intent: intent, response: nil)
                interaction.direction = .incoming
                interaction.donate(completion: nil)
                do {
                    let messageContent = try request.content.updating(from: intent)
                    contentHandler(messageContent)
                } catch {
                    print(error.localizedDescription)
                }

            }

            contentHandler(bestAttemptContent)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        // 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)
        }
    }

}

相關(guān)資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容