Ionic 6推送通知自定义声音与图标无法正常工作求助
Ionic 6 + Angular 推送通知自定义声音/图标不生效问题解决指南
我用Ionic 6搭配Angular开发应用,已经完成设备令牌获取并存储到Firebase数据库,也编写了云函数触发推送通知,但接收通知时自定义声音和图标始终不生效。已经在AndroidManifest.xml中添加了相关meta-data配置,问题仍未解决,求指点遗漏的配置或操作。
排查方向与解决方案
1. 通知负载字段区分
FCM的notification字段属于系统级通知,仅支持本地资源路径(或默认配置),无法直接使用远程URL。如果要使用远程图标/声音,必须将相关参数放到data字段中,然后在前端手动构建通知。
2. 本地资源配置校验
- 图标:确认
@mipmap/icon1对应的图标文件已放置在Android项目的res/mipmap-xxx(各分辨率目录)下,文件名全小写、无特殊字符,且各分辨率版本齐全。 - 声音:
@raw/alert_sound对应的音频文件需放在res/raw目录下,格式为Android支持的.mp3/.wav等,文件名同样需符合小写+下划线的命名规则。
3. 云函数负载调整
如果依赖本地默认配置(AndroidManifest.xml中的设置),无需在notification字段中指定icon或sound;如果要使用远程资源,需修改负载结构:
let notification = { "registration_ids": deviceTokens, "collapse_key": "type_a", "notification": { "body": req.body.desc, "title": req.body.title }, "data": { "icon": "远程图标URL", "sound": "远程音频URL" } };
同时前端需监听通知并手动创建:
PushNotifications.addListener('pushNotificationReceived', (notification: PushNotificationSchema) => { PushNotifications.create({ title: notification.title, text: notification.body, icon: notification.data?.icon, sound: notification.data?.sound }); });
4. FCM权限与发送配置
- 确认云函数中
Authorization的Key是Firebase控制台项目设置-云消息服务中的服务器密钥,而非Web API密钥。 - 避免使用
on("value")监听数据库(会触发多次回调),改用once("value")获取令牌列表:
admin.database().ref('deviceToken').once("value", snap => { // 原有逻辑 });
5. 测试环境注意事项
- 必须使用真实Android设备测试,模拟器对自定义通知资源支持有限。
- 测试时需将应用置于后台或完全关闭,前台通知由Ionic框架处理,系统级通知才会读取AndroidManifest.xml配置。
- 清除应用缓存后重新安装,确保新配置生效。
相关代码
前端获取令牌代码
if (isPushNotificationsAvailable) { PushNotifications.requestPermissions().then(result => { if (result.receive === 'granted') { PushNotifications.register(); } }); PushNotifications.addListener('registration', (token: Token) => { this.token = token.value; const tokenRef = ref(db, `deviceToken/${this.token}`); set(tokenRef, this.token); }); PushNotifications.addListener('pushNotificationReceived', (notification: PushNotificationSchema) => { // this.router.navigateByUrl('/new-bookings') }); }
云函数代码
app.post('/sendNotification', function (req, res) { let deviceTokens = []; admin.database().ref('deviceToken').on("value", snap => { let data = snap.val(); if (data) { Object.keys(data).forEach(key => { if (data[key]) { deviceTokens.push(data[key]); } }); console.log(deviceTokens); let notification = { "registration_ids": deviceTokens, "collapse_key": "type_a", "notification": { "body": req.body.desc, "title": req.body.title, // "icon": 'https://images.ctfassets.net/509kpi6dw56l/1CD2g1XQpaJjEzSh2xFnOp/8cb418adda4fd4caad135ebb2056f72a/icon1.png', // "sound": 'https://assets.ctfassets.net/509kpi6dw56l/7aYHya51vKNWFgPmm63RfG/772d1b53496f76eec97252b0d9511e11/Alert.mp3' } }; const options = { method: 'POST', uri: 'https://fcm.googleapis.com/fcm/send', body: notification, json: true, headers: { 'Content-Type': 'application/json', 'Authorization': 'Key' } } request(options).then(function (response) { res.status(200).json(response); }) .catch(function (err) { console.log(err); }) } }) });
AndroidManifest.xml配置
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@mipmap/icon1" /> <meta-data android:name="com.google.firebase.messaging.default_notification_sound" android:resource="@raw/alert_sound" />
内容的提问来源于stack exchange,提问作者Ciry outstation cabs
相关产品推荐
相关产品推荐

