Flutter应用收到推送通知时能否将其存储到本地数据库,尤其iOS端如何实现
完全可以实现,Android、iOS双端都有成熟可落地的方案,你的业务场景本身就是只需要端侧存储通知,这套方案刚好匹配,不需要额外占用服务端存储资源。
实现前置条件
首先需要确保你集成的推送SDK(不管是FCM、APNs,还是国内的极光、个推等厂商推送)支持前台、后台、应用未激活三种状态下的推送内容回调,这是后续存储数据的基础。
各端特殊配置(重点为iOS端)
iOS端必须配置项
- 打开Xcode项目的「Signing & Capabilities」标签,添加「Background Modes」能力,勾选其中的「Remote notifications」选项
- 服务端下发iOS推送的payload中必须携带
content-available: 1字段,iOS系统识别到该字段后,会临时唤醒后台的App,允许执行最长30秒的代码,足够完成本地存储操作 - 注意不要在推送回调中执行超过30秒的耗时任务,否则系统会强制终止App进程
Android端适配要点
- 国内安卓厂商的系统推送通道默认只在前台给App回调通知内容,后台状态下如果要拿到通知内容,需要配置「透传+通知」的组合策略:服务端先下发透传消息,App收到后先存本地,再主动调用系统接口弹出通知栏提醒
- 部分厂商系统会限制App后台活动,需要引导用户给App开启自启动、后台活动权限,避免后台状态下收不到推送回调
本地存储方案选型
根据你的业务需求二选一即可:
- 仅需要存储最近几十条通知、不需要复杂查询:用
shared_preferences,将通知内容转成JSON字符串存入列表即可,实现成本极低 - 需要存储大量历史通知、需要按时间/状态筛选查询:用
sqflite或者isar本地结构化数据库,性能更高,支持增删改查等全操作
核心实现伪代码
// 推送SDK的全局接收回调,所有状态下收到推送都会触发该方法 void handlePushReceived(Map<String, dynamic> pushPayload) async { // 1. 提取通知核心内容 String noticeTitle = pushPayload['title'] ?? ''; String noticeDesc = pushPayload['body'] ?? ''; String uniqueMsgId = pushPayload['msg_id'] ?? ''; Map? extraData = pushPayload['extra']; // 2. 存入本地存储前先按msgId去重,避免重复存储 bool isExisted = await LocalStorage.instance.checkNoticeExist(uniqueMsgId); if (isExisted) return; // 3. 执行存储逻辑 await LocalStorage.instance.insertNotice( msgId: uniqueMsgId, title: noticeTitle, desc: noticeDesc, extra: extraData, createTime: DateTime.now().millisecondsSinceEpoch, ); // 4. 正常弹出系统通知栏提醒 showSystemNotification(title: noticeTitle, body: noticeDesc, payload: pushPayload); }
已知系统限制说明
- iOS端如果用户手动上滑强制杀死App,系统不会唤醒App执行后台代码,只有用户点击通知启动App时,才能拿到通知内容完成存储,这个是iOS系统的强制限制,没有绕过方案
- 国内少部分安卓定制系统会拦截带后台唤醒标记的推送,需要做厂商专属适配
内容的提问来源于stack exchange,提问作者Hardik Joshi
相关产品推荐
相关产品推荐

