You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS NotificationServiceExtension与Flutter应用交互:推送通知解密问题

解决方案

一、在NSE中读取Hive存储的解密信息

Hive是Flutter端的本地存储库,NSE作为iOS原生扩展无法直接调用Flutter的Hive API,你需要通过共享App Group容器来让NSE访问Hive相关的存储内容:

  1. 给主App和NSE配置相同的App Group

    • 在Xcode中分别选中主App target和NSE target,进入Signing & Capabilities,添加App Groups能力,创建并勾选同一个分组(比如group.com.yourapp.hive)
  2. 修改Hive的存储路径到共享容器
    在Flutter主App初始化Hive时,将存储目录设置为App Group的共享路径:

    import 'package:path_provider/path_provider.dart';
    import 'package:hive/hive.dart';
    
    Future<void> initHive() async {
      // 获取App Group共享容器路径
      final appGroupDir = await getApplicationSupportDirectory();
      final sharedPath = "${appGroupDir.path}/../Group Containers/group.com.yourapp.hive/hive";
      Hive.init(sharedPath);
      // 后续打开Hive box的逻辑保持不变
    }
    
  3. 在NSE中读取解密所需信息
    如果你觉得直接解析Hive的二进制文件太麻烦,可以在Flutter端把解密密钥/关键信息单独存入共享容器的UserDefaults中,NSE直接读取即可:

    // NSE中的didReceive方法代码
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        // 访问App Group的UserDefaults
        let userDefaults = UserDefaults(suiteName: "group.com.yourapp.hive")
        if let decryptionKey = userDefaults?.string(forKey: "notification_decryption_key") {
            // 用密钥解密推送数据
            if let encryptedData = bestAttemptContent?.userInfo["encrypted_content"] as? String {
                let decryptedContent = decrypt(encryptedData, key: decryptionKey) // 替换为你的解密逻辑
                bestAttemptContent?.body = decryptedContent
            }
        }
        
        contentHandler(bestAttemptContent ?? request.content)
    }
    

    对应的Flutter端写入逻辑可以通过MethodChannel调用原生代码完成(shared_preferences默认不支持App Group,直接用原生写入更可靠)。

二、替代NSE调用Flutter方法通道的方案

NSE运行在独立后台进程,无法连接主App的Flutter引擎,MethodChannel在这里完全不可用,推荐两种替代思路:

  1. 直接在NSE中完成解密和通知修改
    也就是上面的方案,把解密依赖的信息放到共享容器,NSE直接读取处理,这是最可靠的方式——NSE生命周期短,依赖主App进程容易导致通知处理延迟或失败。

  2. 通过主App后台任务处理
    如果解密逻辑必须在Flutter端完成,可以给推送通知添加content-available: 1配置(iOS端),触发主App后台唤醒,然后在Flutter的FirebaseMessaging.onBackgroundMessage(若使用Firebase推送)中完成解密,再调用本地通知插件展示处理后的内容。但这种方式依赖系统允许主App后台唤醒,可靠性不如NSE直接处理。


内容的提问来源于stack exchange,提问作者PaulHuang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:08:12