You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 02:34:55