如何使用C#调用OneSignal REST API发送静默通知
OneSignal 静默通知推送实现修正
现有代码失效的核心原因
- 携带了
contents字段:只要请求里带contents/headings/subtitle这类通知展示类字段,OneSignal和系统都会把消息判定为普通可见通知,直接弹横幅,不会走静默唤醒应用的逻辑。 - APNs参数位置错误:你把iOS要求的
content-available字段嵌套在自定义数据结构里,OneSignal不会识别解析这个内部字段,需要用平台规定的顶层参数声明。 - 自定义业务字段位置错误:业务自定义键值对不能和系统字段混放,要统一放在
data节点下。 - 额外隐患:每次请求新建
HttpClient实例会触发套接字耗尽问题,高频调用下会出现请求失败。
修正后可直接运行的代码
// 全局单例HttpClient,避免套接字耗尽问题 private static readonly HttpClient _httpClient = new HttpClient(); private static readonly string oneSignalUrl = "https://onesignal.com/api/v1/notifications"; public async Task<HttpResponseMessage> SendSilentNotification(string playerId, string appId, string restApiKey) { _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + restApiKey); var requestPayload = new { app_id = appId, // iOS静默推送必填:标记为背景内容可用推送,服务端会自动拼接符合APNs要求的aps结构 content_available = true, // 安卓静默推送必填:标记为纯数据消息,避免系统自动弹出通知栏 android_background_data = true, // 注意:此处绝对不能加contents、headings等展示类字段 // 所有自定义业务参数全部放在data节点下 data = new { acme1 = "logout" }, include_player_ids = new[] { playerId } }; var requestContent = new StringContent( JsonConvert.SerializeObject(requestPayload), Encoding.UTF8, "application/json" ); return await _httpClient.PostAsync(oneSignalUrl, requestContent); }
落地注意事项
- 平台限制:iOS对静默推送有严格限流,系统会根据设备电量、网络状态决定是否投递,不保证100%即时到达,不要用来承载高实时性业务;传
content_available = true时OneSignal会自动把APNs推送优先级设为要求的5,不需要手动调整。 - 安卓适配:国内定制ROM需要手动给应用开启后台运行、自启动权限,否则应用被杀进程后无法接收静默推送;搭载谷歌服务的海外设备要确保FCM服务正常运行。
- 调试技巧:调用接口后直接读取返回的JSON字符串,如果返回结果包含
id字段说明请求已经被OneSignal服务端受理;如果返回errors数组,直接根据数组内的报错信息排查即可,常见问题为playerId和appId不匹配、REST API Key填写错误。 - 如果后续需要发送带可见内容、同时携带自定义业务数据的普通推送,再补充
contents字段即可,自定义数据仍然放在data节点,不要和系统字段混放。
内容的提问来源于stack exchange,提问作者Cipher
相关产品推荐
相关产品推荐

