如何在React Native中实现Agora语音通话后台运行?
React Native Agora 后台语音通话解决方案
核心问题分析
- 离开页面后无声音:未配置后台音频权限,系统挂起了音频会话
- 静音/扬声器状态失效:未在后台保持Agora引擎实例,状态未同步到后台服务
前置配置
iOS 配置
在Info.plist中添加后台音频权限和麦克风权限声明:
<key>UIBackgroundModes</key> <array> <string>audio</string> </array> <key>NSMicrophoneUsageDescription</key> <string>需要使用麦克风进行语音通话</string>
Android 配置
在AndroidManifest.xml中添加必要权限和后台服务声明:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application> <!-- 声明前台通话服务 --> <service android:name=".AgoraCallService" android:foregroundServiceType="microphone|mediaPlayback" /> </application>
完整示例代码
1. Android 后台服务实现
创建AgoraCallService.java,用于在后台维持Agora引擎实例:
package com.yourapp; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.Build; import android.os.IBinder; import io.agora.rtc2.RtcEngine; import io.agora.rtc2.RtcEngineConfig; public class AgoraCallService extends Service { private static final String CHANNEL_ID = "AgoraCallChannel"; private RtcEngine mRtcEngine; @Override public void onCreate() { super.onCreate(); initAgoraEngine(); startForeground(1, createForegroundNotification()); } private void initAgoraEngine() { try { RtcEngineConfig config = new RtcEngineConfig(); config.mContext = getBaseContext(); config.mAppId = "YOUR_AGORA_APP_ID"; // 替换为你的Agora App ID config.mEventHandler = new io.agora.rtc2.IRtcEngineEventHandler() {}; mRtcEngine = RtcEngine.create(config); mRtcEngine.enableAudio(); } catch (Exception e) { throw new RuntimeException("Agora引擎初始化失败: " + e.getMessage()); } } private Notification createForegroundNotification() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( CHANNEL_ID, "语音通话", NotificationManager.IMPORTANCE_LOW ); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); } return new Notification.Builder(this, CHANNEL_ID) .setContentTitle("正在进行语音通话") .setContentText("后台保持通话连接") .setSmallIcon(R.drawable.ic_notification) // 替换为你的通知图标 .build(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { String channelName = intent.getStringExtra("CHANNEL_NAME"); String token = intent.getStringExtra("TOKEN"); if (channelName != null && mRtcEngine != null) { mRtcEngine.joinChannel(token, channelName, "", 0); } return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); if (mRtcEngine != null) { mRtcEngine.leaveChannel(); RtcEngine.destroy(); } } @Override public IBinder onBind(Intent intent) { return null; } // 对外暴露静音控制方法 public void setLocalMuted(boolean muted) { if (mRtcEngine != null) { mRtcEngine.muteLocalAudioStream(muted); } } // 对外暴露扬声器控制方法 public void setSpeakerEnabled(boolean enabled) { if (mRtcEngine != null) { mRtcEngine.setEnableSpeakerphone(enabled); } } }
2. React Native 端管理类
创建AgoraCallManager.js,统一处理跨平台通话逻辑:
import { NativeModules, Platform, NativeEventEmitter } from 'react-native'; const { AgoraRtcEngine, AgoraCallService } = NativeModules; const eventEmitter = new NativeEventEmitter(AgoraCallService); class AgoraCallManager { static async startBackgroundCall(channelName, token = null) { if (Platform.OS === 'android') { await AgoraCallService.startService(channelName, token); } else { // iOS 直接初始化引擎并加入频道,依赖后台音频模式 await this.initAgoraEngine(); await this.joinChannel(channelName, token); } } static async initAgoraEngine() { await AgoraRtcEngine.createEngine('YOUR_AGORA_APP_ID'); // 替换为你的Agora App ID await AgoraRtcEngine.enableAudio(); } static async joinChannel(channelName, token) { await AgoraRtcEngine.joinChannel(token, channelName, '', 0); } static async toggleMute(isMuted) { await AgoraRtcEngine.muteLocalAudioStream(isMuted); if (Platform.OS === 'android') { await AgoraCallService.setLocalMuted(isMuted); } } static async toggleSpeaker(isEnabled) { await AgoraRtcEngine.setEnableSpeakerphone(isEnabled); if (Platform.OS === 'android') { await AgoraCallService.setSpeakerEnabled(isEnabled); } } static async endCall() { await AgoraRtcEngine.leaveChannel(); await AgoraRtcEngine.destroyEngine(); if (Platform.OS === 'android') { await AgoraCallService.stopService(); } } } export default AgoraCallManager;
3. 页面调用示例
import React, { useState } from 'react'; import { View, Button, Switch, Text, StyleSheet } from 'react-native'; import AgoraCallManager from './AgoraCallManager'; const CallScreen = () => { const [isMuted, setIsMuted] = useState(false); const [speakerEnabled, setSpeakerEnabled] = useState(true); const startCall = async () => { await AgoraCallManager.startBackgroundCall('test-call-channel'); }; const handleMuteToggle = async () => { const newState = !isMuted; setIsMuted(newState); await AgoraCallManager.toggleMute(newState); }; const handleSpeakerToggle = async () => { const newState = !speakerEnabled; setSpeakerEnabled(newState); await AgoraCallManager.toggleSpeaker(newState); }; return ( <View style={styles.container}> <Button title="开始通话" onPress={startCall} /> <View style={styles.controlRow}> <Text>静音</Text> <Switch value={isMuted} onValueChange={handleMuteToggle} /> </View> <View style={styles.controlRow}> <Text>扬声器</Text> <Switch value={speakerEnabled} onValueChange={handleSpeakerToggle} /> </View> <Button title="结束通话" onPress={AgoraCallManager.endCall} color="red" /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', gap: 20, }, controlRow: { flexDirection: 'row', alignItems: 'center', gap: 10, }, }); export default CallScreen;
关键注意事项
- 使用Agora SDK v4.x最新稳定版,确保后台兼容性
- Android必须将服务设置为前台服务,避免被系统回收
- iOS需开启后台音频模式,否则切换后台会中断音频流
- 静音/扬声器状态需同时同步到引擎实例和后台服务(Android端)
内容的提问来源于stack exchange,提问作者sxchintha
相关产品推荐
相关产品推荐

