React Native实现无用户交互时后台/关闭状态下连接WebSocket
React Native 后台/关闭状态下唤醒应用并连接WebSocket实现音频流接收
你的核心问题在于应用完全关闭或未提前进入后台活跃状态时,无法主动启动WebSocket连接和mediasoup会话,这需要结合平台原生的推送唤醒机制+后台任务保活来解决,以下是分平台的具体实现方案:
iOS 端实现
iOS对后台应用的限制严格,只有通过静默推送才能唤醒关闭/后台的应用,配合后台权限实现持久化连接:
- 配置后台权限:在Xcode中开启
Background Modes,勾选Remote notifications和Voice over IP(或Audio, AirPlay, and Picture in Picture),确保音频相关任务能在后台持续运行。 - 静默推送触发:推送服务器发送的payload必须包含
content-available: 1,示例payload:{"aps": {"content-available": 1}, "type": "audio-invite"} - 唤醒后执行逻辑:在
AppDelegate中实现didReceiveRemoteNotification回调,收到音频呼叫类推送时,立即初始化WebSocket连接、启动mediasoup传输,并通过react-native-background-actions启动后台任务延长执行时间。
Android 端实现
Android的后台唤醒机制更灵活,依赖FCM数据推送+前台服务:
- FCM数据消息唤醒:使用FCM的数据消息(而非通知消息),这类消息会直接传递给应用的
FirebaseMessagingService回调,即使应用关闭也能触发。在回调中启动WebSocket连接和mediasoup会话。 - 前台服务保活:Android 8.0+限制后台服务,需通过
react-native-background-actions配置前台服务(显示一个持续通知),避免被系统回收。 - 自启动权限适配:国产ROM(小米、华为等)有自启动限制,需引导用户开启应用的自启动权限,否则推送可能无法唤醒关闭的应用。
- 心跳保活:在后台任务中定期发送WebSocket心跳包,保持连接活跃,同时监听网络状态,网络恢复时自动重连。
WebSocket 与 mediasoup 适配要点
- 唤醒后的连接流程:应用被推送唤醒后,先建立WebSocket连接到服务器,发送用户在线状态更新,请求服务器初始化mediasoup的传输通道和音频轨道。
- 音频会话配置:
- iOS:将
AVAudioSession设置为AVAudioSessionCategoryPlayAndRecord并激活,确保后台音频不被暂停。 - Android:申请
RECORD_AUDIO和MODIFY_AUDIO_SETTINGS权限,在后台任务中保持音频焦点。
- iOS:将
- 错误重连机制:WebSocket断开时,采用指数退避策略(如1s、3s、5s)重试连接,避免频繁请求服务器。
关键代码片段
iOS 静默推送处理(AppDelegate.m)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { if ([userInfo[@"type"] isEqualToString:@"audio-invite"]) { // 初始化WebSocket连接 [RNWebSocketClient connectToServer]; // 启动后台任务 [RNBackgroundActions startBackgroundTask]; // 初始化mediasoup传输 [RNMediasoupClient setupAudioTransport]; } completionHandler(UIBackgroundFetchResultNewData); }
Android FCM 消息处理(MyFirebaseMessagingService.java)
@Override public void onMessageReceived(RemoteMessage remoteMessage) { Map<String, String> data = remoteMessage.getData(); if ("audio-invite".equals(data.get("type"))) { // 启动前台服务 Intent serviceIntent = new Intent(this, BackgroundAudioService.class); ContextCompat.startForegroundService(this, serviceIntent); // 连接WebSocket WebSocketClient.connect(); // 初始化mediasoup MediasoupClient.setupTransport(); } }
React Native 后台任务配置
import BackgroundService from 'react-native-background-actions'; const keepAliveTask = async () => { setInterval(() => { if (global.webSocket?.readyState === WebSocket.OPEN) { global.webSocket.send(JSON.stringify({type: 'heartbeat'})); } else { global.webSocket?.reconnect(); } }, 30000); // 30秒发送一次心跳 }; const taskOptions = { taskName: 'Audio Stream Service', taskTitle: '音频流服务运行中', taskDesc: '正在接收音频通话', taskIcon: {name: 'ic_launcher', type: 'mipmap'}, foreground: true, // Android必须启用前台服务 color: '#2196F3', }; // 推送唤醒后启动后台任务 BackgroundService.start(keepAliveTask, taskOptions);
内容的提问来源于stack exchange,提问作者Utkarsh Agrawal
相关产品推荐
相关产品推荐

