Notification Service Extension: nó là gì, xử lý nội dung trước khi hiển thị trên iOS

Tác giả: IT Sectr Đã đăng: 2026-03-21 Thời gian đọc: 8 phút

Notification Service Extension là một tiện ích mở rộng của iOS chặn thông báo push trước khi hiển thị cho người dùng và cho phép sửa đổi nội dung. Tiện ích mở rộng có thể giải mã dữ liệu đã mã hóa, tải xuống tệp đính kèm phương tiện, thay đổi văn bản hoặc thêm trường tùy chỉnh. Theo Apple Developer, 2025, Notification Service Extension có tối đa 30 giây để hoàn thành tác vụ trong nền.

Những điểm chính

  • Notification Service Extension là tiện ích mở rộng iOS để xử lý thông báo push trước khi hiển thị.
  • Tiện ích mở rộng kế thừa từ UNNotificationServiceExtension và triển khai phương thức didReceive.
  • Tối đa 30 giây thực thi nền để tải xuống và xử lý dữ liệu.
  • Trường hợp sử dụng chính: giải mã payload, tải xuống hình ảnh và video, xác thực nội dung.
  • Tiện ích mở rộng có thể trì hoãn hiển thị thông báo hoặc hủy hoàn toàn thông qua contentHandler.

Notification Service Extension là gì

Notification Service Extension là một tiện ích mở rộng ứng dụng trên iOS chạy trước khi thông báo push được hiển thị. Nó cho phép máy chủ gửi payload tối thiểu trong khi tiện ích mở rộng làm phong phú nó với nội dung: tải xuống hình ảnh, giải mã dữ liệu, thay thế văn bản. Người dùng thấy thông báo đã được xử lý.

Cách hoạt động

Khi iOS nhận được thông báo push, hệ thống kiểm tra xem có tiện ích mở rộng cho ứng dụng hay không. Nếu tiện ích mở rộng được đăng ký, iOS khởi chạy nó trong một tiến trình nền và chuyển nội dung thông báo qua phương thức didReceive(_:withContentHandler:). Tiện ích mở rộng xử lý nội dung và gọi contentHandler với nội dung đã sửa đổi. Nếu tiện ích mở rộng không hoàn thành trong 30 giây, hệ thống hiển thị thông báo gốc.

Khi nào nên sử dụng Service Extension

Service Extension cần thiết trong các kịch bản mà nội dung thông báo yêu cầu xử lý trên thiết bị. Truyền thông an toàn: máy chủ gửi payload đã mã hóa, tiện ích mở rộng giải mã cục bộ. Thông báo đa phương tiện phong phú: máy chủ gửi URL hình ảnh, tiện ích mở rộng tải xuống và đính kèm. Bản địa hóa động: tiện ích mở rộng thay thế văn bản bằng ngôn ngữ của thiết bị.

Kịch bảnKhông có tiện ích mở rộngCó tiện ích mở rộng
Hình ảnhKhông được hỗ trợĐược tải xuống và hiển thị
Mã hóaMáy chủ giữ khóaGiải mã trên thiết bị
Văn bảnCố định trên máy chủThay thế động
Xác thựcKhông được kiểm traHủy thông báo độc hại

Giới hạn và thời gian thực thi

Notification Service Extension hoạt động trong môi trường giới hạn. Thời gian thực thi tối đa là 30 giây. Tiện ích mở rộng không có quyền truy cập vào bộ nhớ chính của ứng dụng (ngoại trừ App Group). Kích thước tiện ích mở rộng bị giới hạn ở 50 MB. Khi vượt quá thời gian, hệ thống gọi contentHandler với nội dung gốc và tất cả các thay đổi đều bị mất.

Tạo tiện ích mở rộng và cấu hình Info.plist

Trong Xcode, Notification Service Extension được thêm bằng cách tạo một target mới loại Notification Service Extension. Xcode tạo một lớp mẫu NotificationService kế thừa từ UNNotificationServiceExtension, với hai phương thức: didReceive và serviceExtensionTimeWillExpire.

Thêm target vào dự án

Trong Xcode, chọn File → New → Target → Notification Service Extension. Nhập tên (ví dụ: PushNotificationService) và chọn ngôn ngữ Swift. Đảm bảo rằng target được thêm vào ứng dụng chính và có chữ ký chính xác. Sau khi tạo, lớp NotificationService.swift với triển khai cơ bản sẽ được tạo.

Cấu trúc Info.plist của tiện ích mở rộng

Info.plist của tiện ích mở rộng chứa khóa NSExtension với các khóa con NSExtensionPointIdentifier (com.apple.usernotifications.service) và NSExtensionPrincipalClass (tên bộ điều khiển của bạn). Ngoài ra, có thể chỉ định NSExtensionAttributes với các quy tắc kích hoạt tiện ích mở rộng. Xcode tạo các cài đặt này tự động.

Ví dụ tiện ích mở rộng cơ bản

Triển khai cơ bản ghi đè didReceive, sửa đổi nội dung thông báo và gọi contentHandler. Nếu quá trình xử lý mất quá nhiều thời gian, serviceExtensionTimeWillExpire được gọi, nơi bạn cần hoàn thành công việc với trạng thái hiện tại.

swift
import UserNotifications

class NotificationService: UNNotificationServiceExtension {

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

    override func didReceive(
        request: UNNotificationRequest,
        withContentHandler handler: @escaping (UNNotificationContent) -> Void
    ) {
        contentHandler = handler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        if let bestAttemptContent = bestAttemptContent {
            bestAttemptContent.title = "[Đã xử lý] \(bestAttemptContent.title)"
            contentHandler?(bestAttemptContent)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler,
           let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}

Giải mã payload đã mã hóa

Một trong những ứng dụng chính của Service Extension là giải mã nội dung thông báo trên thiết bị. Máy chủ gửi một payload đã mã hóa và tiện ích mở rộng giải mã nó bằng khóa được lưu trữ trong Keychain hoặc App Group. Điều này đảm bảo nội dung không thể bị chặn trong quá trình truyền.

Kiến trúc phân phối an toàn

Máy chủ mã hóa nội dung thông báo bằng khóa đối xứng (AES-256). Khóa mã hóa được thỏa thuận trước giữa máy khách và máy chủ. Tiện ích mở rộng nhận chuỗi đã mã hóa trong trường data của payload, giải mã nó và thay thế vào các trường thông báo. Khóa người dùng có thể được lấy từ Keychain sau khi xác thực.

swift
override func didReceive(
    request: UNNotificationRequest,
    withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
    guard let content = request.content.mutableCopy()
        as? UNMutableNotificationContent else {
        handler(request.content)
        return
    }

    guard let encryptedData = content.userInfo["encrypted_data"]
        as? String else {
        handler(content)
        return
    }

    let decrypted = CryptoService.decrypt(encryptedData)
    content.body = decrypted.body
    content.title = decrypted.title
    handler(content)
}

Lưu trữ khóa an toàn

Khóa giải mã không được lưu trữ trong mã tiện ích mở rộng hoặc NSUserDefaults. Sử dụng iOS Keychain với quyền truy cập qua App Group để cả ứng dụng và tiện ích mở rộng đều có thể đọc khóa. Sử dụng Security.framework với thuật toán AES-256-GCM để tạo khóa trên máy khách.

Tải xuống và đính kèm tệp phương tiện

Cách sử dụng phổ biến nhất của Notification Service Extension là tải xuống hình ảnh, GIF và video để hiển thị trong thông báo. Máy chủ gửi URL tệp phương tiện và tiện ích mở rộng tải xuống, lưu vào thư mục tạm thời và tạo UNNotificationAttachment.

Quy trình tải xuống và đính kèm phương tiện

Tiện ích mở rộng nhận URL hình ảnh từ trường payload của thông báo. Sử dụng URLSession, tiện ích mở rộng tải tệp xuống thư mục tạm thời. Sau khi tải xuống hoàn tất, UNNotificationAttachment với URL cục bộ được tạo. Tệp đính kèm được chuyển đến nội dung đã sửa đổi. iOS tự động hiển thị hình ảnh trong giao diện tiêu chuẩn hoặc trong Notification Content Extension.

swift
private func downloadAndAttachMedia(
    content: UNMutableNotificationContent,
    mediaUrl: String,
    handler: @escaping (UNNotificationContent) -> Void
) {
    guard let url = URL(string: mediaUrl) else {
        handler(content)
        return
    }

    let task = URLSession.shared.downloadTask(with: url) { localUrl, _, error in
        guard let localUrl = localUrl, error == nil else {
            handler(content)
            return
        }

        let attachment = try? UNNotificationAttachment(
            identifier: "media",
            url: localUrl,
            options: nil
        )

        if let attachment = attachment {
            content.attachments = [attachment]
        }
        handler(content)
    }
    task.resume()
}

Định dạng phương tiện được hỗ trợ

iOS hỗ trợ các định dạng sau để hiển thị trong thông báo: JPEG, PNG, GIF (tĩnh), video MPEG-4 lên đến 50 MB. Đối với tệp âm thanh, MP3, AAC và ALAC được hỗ trợ. Quan trọng: tất cả các tệp phương tiện phải được tải xuống trong giới hạn 30 giây. Đối với tệp lớn, nên cắt phía máy chủ hoặc tải dần.

Quản lý thời gian và các kịch bản dự phòng

Quản lý giới hạn 30 giây là một nhiệm vụ quan trọng khi phát triển Notification Service Extension. Nếu tiện ích mở rộng không hoàn thành xử lý kịp thời, hệ thống gọi serviceExtensionTimeWillExpire và hiển thị nội dung gốc. Các kịch bản dự phòng phải được cung cấp cho mỗi loại xử lý.

Chiến lược ưu tiên

Chia nhiệm vụ theo mức độ ưu tiên. Thực hiện các sửa đổi quan trọng (giải mã, bản địa hóa cơ bản) trước. Các cải tiến tùy chọn (tải xuống hình ảnh, làm phong phú văn bản) thực hiện sau. Sử dụng URLSession với thời gian chờ cho các yêu cầu mạng để tránh dành toàn bộ giới hạn cho một thao tác duy nhất.

Dự phòng khi có lỗi

Nếu tải xuống hình ảnh thất bại hoặc giải mã payload trả về lỗi, tiện ích mở rộng nên gọi contentHandler với nội dung gốc. Không bao giờ kết thúc tiện ích mở rộng mà không gọi contentHandler — điều này dẫn đến mất thông báo. Dự phòng an toàn phải luôn được bao gồm trong mã tiện ích mở rộng.

swift
override func didReceive(
    request: UNNotificationRequest,
    withContentHandler handler: @escaping (UNNotificationContent) -> Void
) {
    let content = (request.content.mutableCopy()
        as? UNMutableNotificationContent) ?? request.content

    // Nhiệm vụ quan trọng: giải mã
    var decryptedContent = tryDecryptPayload(content)

    // Nhiệm vụ tùy chọn: phương tiện
    guard let mediaUrl = decryptedContent.userInfo["media_url"]
        as? String else {
        handler(decryptedContent)
        return
    }

    downloadAndAttachMedia(
        content: decryptedContent,
        mediaUrl: mediaUrl,
        handler: handler
    )
}

Kiểm tra tiện ích mở rộng

Để kiểm tra Notification Service Extension, hãy sử dụng Xcode: chọn target tiện ích mở rộng, chạy trên trình mô phỏng và gửi thông báo push qua terminal hoặc Firebase Console. Ghi nhật ký từng giai đoạn xử lý bằng os_log — điều này giúp chẩn đoán các vấn đề về thời gian và tải xuống.

Câu hỏi thường gặp

Điều gì xảy ra nếu tiện ích mở rộng không hoàn thành trong 30 giây?

Hệ thống gọi serviceExtensionTimeWillExpire, sau đó hiển thị thông báo gốc mà không thay đổi. Tất cả các tệp đã tải xuống và sửa đổi đều bị loại bỏ.

Có thể hủy hiển thị thông báo từ tiện ích mở rộng không?

Có, nếu bạn gọi contentHandler với nội dung trống (UNNotificationContent với các trường trống), thông báo sẽ không được hiển thị. Điều này được sử dụng để lọc thông báo rác hoặc dữ liệu không chính xác.

Làm thế nào để truyền mã thông báo ủy quyền để tải phương tiện?

Mã thông báo có thể được truyền trong userInfo của payload thông báo hoặc lấy từ Keychain qua App Group. Không khuyến nghị lưu trữ mã thông báo trong UserDefaults của tiện ích mở rộng.

Có cần cấu hình chứng chỉ đặc biệt cho tiện ích mở rộng không?

Tiện ích mở rộng phải được ký bằng cùng chứng chỉ nhà phát triển với ứng dụng chính. Đối với sản xuất, cần có chứng chỉ sản xuất với khả năng Push Notifications được bật.

Làm thế nào để gỡ lỗi tiện ích mở rộng trên thiết bị thực?

Kết nối thiết bị với Xcode, chọn target tiện ích mở rộng trong lược đồ chạy và gửi thông báo push qua Firebase Console. Điểm dừng trong tiện ích mở rộng hoạt động giống như trong ứng dụng chính.

Tóm tắt

  • Notification Service Extension là tiện ích mở rộng iOS để xử lý nền các thông báo push trước khi hiển thị.
  • Thời gian thực thi tối đa là 30 giây, sau đó hệ thống hiển thị nội dung gốc.
  • Trường hợp sử dụng chính: giải mã payload, tải xuống phương tiện, xác thực và bản địa hóa nội dung.
  • Tiện ích mở rộng kế thừa từ UNNotificationServiceExtension với các phương thức didReceive và serviceExtensionTimeWillExpire.
  • Để tải phương tiện, sử dụng URLSession, để lưu trữ khóa, sử dụng iOS Keychain.
  • Luôn cung cấp dự phòng — gọi contentHandler với nội dung gốc khi có lỗi.
  • Kết hợp Service Extension với Content Extension để kiểm soát hoàn toàn thông báo.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm