如何在Capacitor构建的Ionic Angular应用内发送推送通知
核心实现逻辑
首先明确一个强制规则:Firebase Cloud Messaging 不允许直接从客户端应用向其他设备发送推送,所有推送发送请求必须经过你可控的后端服务调用FCM/APNs接口触发——如果把FCM服务端密钥放在前端代码里,会被反编译泄露,任何人都能盗用你的配额给你的用户发垃圾推送,严重时会直接被Google封禁Firebase项目权限。
你现在已经完成了终端设备的推送注册、token获取、接收监听的基础逻辑,要实现业务场景的自动推送,整体只需要补3个环节:
- 第一步:把用户拿到的设备推送token和当前登录的用户ID绑定,存到你的业务数据库
- 第二步:在业务触发点(比如入群申请提交、新消息发送成功)调用你自己的后端接口,把推送接收人、推送标题、内容、跳转参数传给后端
- 第三步:后端拿到请求后,调用FCM官方服务端接口给对应目标token发推送,终端用户就能自动收到系统通知
前端代码改造点
你现有的NotificationsService只完成了推送权限申请和基础接收监听,缺两个核心逻辑:拿到token后上报后端绑定用户、应用前台状态下的通知弹窗兼容,改造后的可直接参考的代码如下:
import { Injectable } from '@angular/core'; import { Capacitor } from '@capacitor/core'; import { ActionPerformed, PushNotificationSchema, PushNotifications, Token, } from '@capacitor/push-notifications'; import { HttpClient } from '@angular/common/http'; import { AuthService } from './auth.service'; // 替换为你项目自己的登录态服务,用于获取当前登录用户ID import { LocalNotifications } from '@capacitor/local-notifications'; // 用于前台收到推送时手动弹系统通知条 @Injectable({ providedIn: 'root' }) export class NotificationsService { // 替换为你自己的后端服务接口地址 private readonly apiBase = 'https://your-backend-domain/api'; constructor( private http: HttpClient, private auth: AuthService ) { } initPush() { if (Capacitor.getPlatform() !== 'web') { this.registerPush(); } } public registerPush() { PushNotifications.requestPermissions().then((permission) => { if (permission.receive === 'granted') { // 向APNs/FCM注册推送服务 PushNotifications.register(); } }); PushNotifications.addListener( 'registration', (token: Token) => { console.log('当前设备推送token:', token.value); // 核心逻辑:将token和当前用户绑定上报到后端存储 this.uploadPushToken(token.value).subscribe(); } ); PushNotifications.addListener('registrationError', (error: any) => { console.log('推送注册失败:', error); }); // 应用在前台打开时,系统默认不会弹通知条,需要手动触发本地通知 PushNotifications.addListener( 'pushNotificationReceived', async (notification: PushNotificationSchema) => { console.log('收到推送内容:', notification); await LocalNotifications.schedule({ notifications: [ { title: notification.title || '', body: notification.body || '', id: Date.now(), extra: notification.data } ] }); } ); PushNotifications.addListener( 'pushNotificationActionPerformed', async (notification: ActionPerformed) => { const data = notification.notification.data; console.log('用户点击推送:', notification.notification); if (data.detailsId) { // 在这里写跳转逻辑,比如跳转到对应群聊页、入群审核页 // this.router.navigateByUrl(`/group/${data.groupId}`); } } ); } // 上报推送token到后端的方法 private uploadPushToken(token: string) { const currentUserId = this.auth.getCurrentUserId(); return this.http.post(`${this.apiBase}/push-token/bind`, { userId: currentUserId, deviceToken: token, platform: Capacitor.getPlatform() }); } }
后端实现要点
后端不需要复杂逻辑,只需要实现两个基础能力即可:
- token绑定接口:接收前端上报的用户ID和设备token,存入数据库。注意一个用户可能在多个设备登录(手机、平板),要存多条token记录,用户主动退出登录时要同步删除对应设备的token,避免给已登出的设备发推送。
- 通用推送触发逻辑:在业务事件完成后自动触发推送,流程为:
- 根据业务场景定位需要接收通知的用户ID,从数据库查询该用户绑定的所有有效设备token
- 用Firebase Admin SDK初始化FCM服务(服务账号密钥仅存在后端,绝对不能下发到前端)
- 构造推送消息体,填入标题、正文、自定义跳转参数,批量向目标token下发推送
业务场景示例:用户A提交加入群组B的申请时,前端调用后端的入群申请接口,后端完成入群申请数据写入后,立刻查询群组B群主绑定的所有设备token,调用FCM接口发送标题为「入群申请」、内容为
${用户A的昵称} 想要加入你的群组的推送,群主的设备不管应用在前台、后台还是被杀进程,都能收到系统通知。新消息提醒的触发逻辑完全一致,在消息入库完成后触发推送即可。
注意事项
- iOS平台需要额外配置APNs推送证书,上传到Firebase控制台后才能正常收到推送
- 推送内容属于明文传输,不要在推送的自定义参数里放密码、身份证号这类敏感信息
- 不要尝试在前端直接调用FCM的发送接口,服务端凭证泄露会导致项目被滥用
- 用户关闭推送权限时,要在前端做合理的弹窗引导,避免用户错过关键通知
内容的提问来源于stack exchange,提问作者Idrees Ageed
相关产品推荐
相关产品推荐

