You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
最佳实践
通话打断和恢复
复制全文
下载 pdf
通话打断和恢复
用户在进行实时音视频通话的过程中,可能会被系统电话,第三方应用,或其他系统行为打断音视频采集,大部分情况下,RTC 将在打断结束时,自动恢复音视频采集,详见下表。你需要根据实际业务场景,考虑在不同打断事件中,是否同步音视频的采集状态,以及如何维护远端音视频订阅状态。​
例如,在安卓平台的 1 v 1 通话场景中,本端用户在 RTC 通话中接听了系统电话,预期 RTC 的音频和视频均暂停采集,远端音视频流暂停播放。但此时只有音频会暂停,视频仍然正常采集和发布。因此,你需要在收到暂停状态回调时,调用相应接口,停止视频采集、取消远端音视频流订阅。并在收到自动恢复回调后,重新开启视频采集、订阅远端音视频流。​
音视频采集打断和自动恢复​
在不同的打断事件中,RTC SDK 的音视频采集状态如下表。​
​
打断事件​
Android​
iOS​
Windows/macOS​
系统电话​
音频:暂停,通话结束后自动恢复​
视频:正常​
音频:暂停,通话结束后自动恢复​
视频:被打断​
不适用​
第三方应用 (占用音视频采集设备)​
音视频:暂停,占用结束后自动恢复​
音视频:暂停,占用结束后自动恢复​
由操作系统决定,例如设备被抢占导致 RTC 采集不到数据,将回调相应状态​
锁屏​
音视频:正常​
音视频:正常​
PC 合盖(系统未休眠)​
不适用​
不适用​
音频:正常​
视频:正常,但合盖后摄像头采集不到人像,用户也看不到远端画面​
iOS 应用处于侧拉、分屏或者画中画模式​
iOS 系统性能不足(如设备过热)​
iOS 应用切换到后台​
不适用​
视频:被打断,将回调设备采集状态,打断结束后自动恢复​
不适用​
​
默认情况下,SDK 会监听 Android 系统电话事件,在系统通话期间关闭音频模块。确保 app 中没有包含拦截系统电话事件( CALL_STATE_IDLE 和 CALL_STATE_OFFHOOK )的业务逻辑,否则 RTC 将无法感知系统电话,可能造成用户通话时仍继续发送音视频流。​
管理采集打断期间的音视频采集和订阅​
不同打断事件中,你需要关注音视频采集打断和自动恢复状态,以便同时控制视频采集、维护远端音视频流的订阅关系。​
通过监听 onAudioDeviceStateChanged 和 onVideoDeviceStateChanged 回调,了解采集设备被打断和自动恢复的情况。​
自 3.38.1 开始,RTC SDK 新增以下枚举值,反映当前打断状态。​
  • InterruptionBegan : 被打断。Android 目前无法监听音频采集被第三方应用打断/恢复的事件,可以监听被打断后的静音采集错误​
  • InterruptionEnded : 已恢复​
  1. 在 RTC 通话被打断时,调用 pauseAllSubscribedStream 暂停接收所有远端用户。 按照上方表格,指定暂停接收的媒体流类型为音频或视频。调用 stopVideoCapture 同时暂停视频采集。​
  1. 在 RTC 通话从打断中恢复时,调用 resumeAllSubscribedStreamVideo/resumeAllSubscribedStreamAudio 恢复订阅所有远端用户的音视频流。监听以下回调,了解音视频的采集状态。调用 startVideoCapture 同时开启视频采集。​
  1. onAudioDeviceStateChanged 、 onVideoDeviceStateChanged​
  • state: RuntimeError​
  • error: DeviceNoCallback​
  1. onAudioDeviceWarning 、 onVideoDeviceWarning​
  • warning: CaptureSilence​
当从以上回调监听到采集异常时,你可以尝试通过再次调用 startVideoCapture 或 startAudioCapture 来进行恢复。​
Android 9 及以上实现锁屏后继续采集音视频​
由于 Android 9 以上版本的 系统限制 ,部分 Android 手机在锁屏后采集音视频失败,解锁后音频采集自动恢复。如果你希望锁屏后仍能采集音频或视频,建议按照以下步骤,在合适时机启用一个前台 service。​
  1. 在 AndroidManifest.xml 中引入前台服务权限和 service。​
  • 可将 microphone 修改为 camera 实现在锁屏后继续采集视频。​
  • ​
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />​
    ​
    <service​
    android:name="com.ss.demo.service.RoomKeepLifeService"​
    android:foregroundServiceType="microphone"​
    tools:node="merge" />​
    ​
  1. 继承系统 Service,并重载相关的函数,实现 service 的启动和停止。​
  • ​
    package com.ss.demo.service;​
    ​
    import android.app.Notification;​
    import android.app.NotificationChannel;​
    import android.app.NotificationManager;​
    import android.app.PendingIntent;​
    import android.app.Service;​
    import android.content.Intent;​
    import android.content.pm.ServiceInfo;​
    import android.os.Build;​
    import android.os.IBinder;​
    import android.support.annotation.Nullable;​
    import android.support.v4.app.NotificationCompat;​
    ​
    import com.ss.video.rtc.demo.ui.chat.ChatActivity;​
    ​
    public class RoomKeepLifeService extends Service {​
    public static final String CHANNEL_ID = "RoomKeepLifeServiceChannel";​
    private static final String COMMAND = "command";​
    private static final String COMMAND_START = "start";​
    private static final String COMMAND_STOP = "stop";​
    ​
    @Nullable​
    @Override​
    public IBinder onBind(Intent intent) {​
    return null;​
    }​
    ​
    @Override​
    public void onCreate() {​
    super.onCreate();​
    startAsForeground(new Intent());​
    }​
    ​
    @Override​
    public int onStartCommand(Intent intent, int flags, int startId) {​
    if(intent != null){​
    switch (intent.getStringExtra(COMMAND)){​
    case COMMAND_START:​
    startAsForeground(intent);​
    break;​
    case COMMAND_STOP:​
    stopInternal();​
    break;​
    default:​
    break;​
    }​
    }​
    ​
    return super.onStartCommand(intent, flags, startId);​
    }​
    ​
    public void stopInternal() {​
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {​
    stopForeground(true);​
    stopSelf();​
    }​
    }​
    ​
    private void startAsForeground(Intent intent) {​
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {​
    createNotificationChannel();​
    Intent notificationIntent = new Intent(this, ChatActivity.class); // 请替换为实际的 Activity​
    PendingIntent pendingIntent = PendingIntent.getActivity(this,​
    0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);​
    ​
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)​
    .setContentTitle("房间正在进行中...")​
    .setSmallIcon(com.ss.video.rtc.common.R.drawable.icon_default_avatar)​
    .setContentIntent(pendingIntent)​
    .setShowWhen(false)​
    .build();​
    ​
    startForeground(110, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);​
    }​
    }​
    ​
    private void createNotificationChannel() {​
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {​
    NotificationChannel serviceChannel = new NotificationChannel(​
    CHANNEL_ID,​
    "Foreground Service Channel",​
    NotificationManager.IMPORTANCE_DEFAULT​
    );​
    ​
    NotificationManager manager = getSystemService(NotificationManager.class);​
    if (manager != null) {​
    manager.createNotificationChannel(serviceChannel);​
    }​
    }​
    }​
    }​
    ​
  1. 根据业务需要,在合适的时机启动和停止 service。以下示例以进房启动,退房停止为例。​
  • ​
    public void joinRoom() {​
    // -- 启动服务 -- //​
    startRoomKeepLifeService();​
    ​
    // -- 进房相关操作 -- //​
    // ...​
    }​
    ​
    public void leaveRoom() {​
    // -- 退房相关操作 -- //​
    // ...​
    ​
    // -- 停止服务 -- //​
    stopRoomKeepLifeService();​
    }​
    ​
    private void startRoomKeepLifeService() {​
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){​
    // EnvUtilities.getAppContext() 为获取 context 的方法示例,你需要根据项目实际情况进行替换​
    Intent serviceIntent = new Intent(EnvUtilities.getAppContext(), RoomKeepLifeService.class);​
    serviceIntent.putExtra("command", "start");​
    ContextCompat.startForegroundService(EnvUtilities.getAppContext(), serviceIntent);​
    }​
    }​
    ​
    private void stopRoomKeepLifeService(){​
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {​
    // EnvUtilities.getAppContext() 为获取 context 的方法示例,你需要根据项目实际情况进行替换​
    Intent serviceIntent = new Intent(EnvUtilities.getAppContext(), RoomKeepLifeService.class);​
    serviceIntent.putExtra("command", "stop");​
    ContextCompat.startForegroundService(EnvUtilities.getAppContext(), serviceIntent);​
    }​
    }​
    ​
API 参考​
  • Android​
  • iOS​
  • Windows​
​
最近更新时间:2026.08.05 17:28:58
这个页面对您有帮助吗?
有用
有用
无用
无用