实现音视频互动

  • Android

更新时间不可用

了解如何快速接入实时互动 RTC,完成环境准备、参数配置、示例运行和核心流程验证。

本文介绍如何集成声网实时互动 SDK,通过少量代码从 0 开始实现一个简单的实时互动 App,适用于互动直播和视频通话场景。首先,你需要了解以下有关音视频实时互动的基础概念:

  • 声网实时互动 SDK:由声网开发的、帮助开发者在 App 中实现实时音视频互动的 SDK。
  • 频道:用于传输数据的通道,在同一个频道内的用户可以进行实时互动。
  • 主播:可以在频道内发布音视频,同时也可以订阅其他主播发布的音视频。
  • 观众:可以在频道内订阅音视频,不具备发布音视频权限。

更多概念详见关键概念。

下图展示在 App 中实现音视频互动的基本工作流程:

  1. 所有用户调用 joinChannel 方法加入频道,并根据需要设置用户角色:

    • 互动直播:如果用户需要在频道中发流,则设为主播;如果用户只需要收流,则设为观众。
    • 视频通话:将所有用户的角色都设为主播。
  2. 加入频道后,不同角色的用户具备不同的行为:

    • 所有用户默认都可以接收频道中的音视频流。
    • 主播可以在频道内发布音视频流。
    • 观众如果需要发流,可在频道内调用 setClientRole 方法修改用户角色,使其具备发流权限。

前提条件

在实现功能以前,请按照以下要求准备开发环境:

  • Android Studio 4.1 以上版本。
  • Android API 级别 16 或以上。
  • 两台运行 Android 4.1 或以上版本的移动设备。
  • 可以访问互联网的计算机。如果你的网络环境部署了防火墙,参考应对防火墙限制以正常使用声网服务。
  • 一个有效的声网账号以及声网项目。请参考开通 RTC 服务从声网控制台获得 App ID 和临时 Token。

注意

临时 Token 的有效期是 24 小时。Token 过期会导致加入频道失败。

创建项目

本小节介绍如何创建项目并为项目添加体验实时互动所需的权限。

  1. (可选) 创建新项目。详见 Create a project。

    1. 打开 Android Studio,选择 New Project。

    2. 选择 Phone and Tablet > Empty Views Activity,点击 Next。

    3. 设置项目名称和存储路径,选择语言为 Java,点击 Finish 创建 Android 项目。

      注意

      创建项目后,Android Studio 会自动开始同步 Gradle,稍等片刻至同步成功后再进行下一步操作。

  2. 添加网络及设备权限。

    打开 /app/src/main/AndroidManifest.xml 文件,在 </application> 后面添加如下权限:

    XML
    <!--必要权限-->
    <uses-permission android:name="android.permission.INTERNET"/>
    
    <!--可选权限-->
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <!-- 对于 Android 12.0 及以上且集成 v4.1.0 以下 SDK 的设备,还需要添加以下权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    <!-- 对于 Android 12.0 及以上设备,还需要添加以下权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
  3. 防止代码混淆。

    如果你的 App 未开启 R8/ProGuard 缩减和混淆,无需额外配置混淆规则。如果你的 App 开启了 R8/ProGuard 缩减和混淆,请根据集成方式选择以下任一配置:

    • 快速配置:打开 /app/proguard-rules.pro 文件,添加如下规则,保留所有声网 SDK 相关类:

      Java
      -keep class io.agora.**{*;}
      -dontwarn io.agora.**
    • 精细化配置:如果你对 App 包体积、代码缩减或混淆效果有更高要求,可以使用 SDK 提供的 consumer-proguard-rules.pro 文件。该文件仅保留 Native 层通过 JNI 访问所需的 Java 类、成员和方法,使其他 SDK Java 代码可继续参与 R8/ProGuard 的缩减、优化和混淆。

      通过 AAR 集成时,consumer-proguard-rules.pro 已包含在 AAR 中,打包时会自动生效,无需手动拷贝。通过 JAR 集成时,你需要将 consumer-proguard-rules.pro 手动拷贝到工程中,并在 build.gradle 中添加该文件,例如:

      Text
      android {
          buildTypes {
              release {
                  minifyEnabled true
                  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                          'proguard-rules.pro',
                          'consumer-proguard-rules.pro'
              }
          }
      }

集成 SDK

你可以选用以下任一方式集成声网实时互动 SDK。

  1. 进入项目根目录,打开 settings.gradle 文件,在 dependencyResolutionManagement 的 repositories 中添加声网 Maven CDN 仓库。

    请保留项目中已有的 Maven 仓库配置,尤其是 mavenCentral(),并额外添加声网 Maven CDN 仓库。

    注意

    如果你在 settings.gradle 中找不到 dependencyResolutionManagement 字段,可能是因为你的 Android Gradle Plugin 版本低于 v7.1.0。

    相关信息请参考 Android Gradle Plugin Release Note v7.1.0。

    groovy
    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            mavenCentral()
            maven { url = 'https://download.shengwang.cn/maven/' }
        }
    }

    若你的 Android Gradle Plugin 版本低于 v7.1.0,请打开项目根目录下的 build.gradle 文件,在 allprojects 的 repositories 中添加如下配置:

    groovy
    allprojects {
        repositories {
            mavenCentral()
            maven { url = 'https://download.shengwang.cn/maven/' }
        }
    }
  2. 打开 /app/build.gradle 文件,在 dependencies 中添加声网 RTC SDK 的依赖。你可以从发版说明中查询 SDK 的最新版本,并将 x.y.z 替换为具体的版本号。

    groovy
    ...
    dependencies {
        ...
        // 对于 4.6.0 及之后的版本
        // x.y.z 替换为具体的 SDK 版本号,如:4.6.1
        // 集成 Full SDK
        implementation 'cn.shengwang.rtc:full-sdk:x.y.z'
        // 集成 Lite SDK
        implementation 'cn.shengwang.rtc:lite-sdk:x.y.z'
    
        // 对于 4.6.0 之前的版本
        // x.y.z 替换为具体的 SDK 版本号,如:4.0.0 或 4.1.0-1
        // 集成 Full SDK
        implementation 'io.agora.rtc:full-sdk:x.y.z'
        // 或集成 Lite SDK
        implementation 'io.agora.rtc:lite-sdk:x.y.z'
    }

    注意

    Lite SDK 默认无法与 RTC 小程序 SDK 互通。如果需要,请联系技术支持。

  1. 在下载页面下载最新版本的 Android 实时互动 SDK,并解压。

  2. 打开解压文件,将以下文件或子文件夹复制到你的项目路径中。

    文件或子文件夹项目路径
    agora-rtc-sdk.jar 文件/app/libs/
    arm64-v8a 文件夹/app/src/main/jniLibs/
    armeabi-v7a 文件夹/app/src/main/jniLibs/
    x86 文件夹/app/src/main/jniLibs/
    x86_64 文件夹/app/src/main/jniLibs/
    high_level_api 中的include 文件夹/app/src/main/jniLibs/
    表格内容超出当前宽度,可横向滚动查看更多列。

    注意

    自 4.5.0 起,RTC SDK 和 RTM SDK (2.2.0 及以上版本) 都包含 libaosl.so 库。如果你通过 CDN 手动集成 RTC SDK 且同时集成了 RTM SDK,为避免冲突,请手动删除版本较低的 libaosl.so 库。4.6.0 RTC SDK libaosl.so 库版本为 1.3.0。

  3. 在 Android Studio 的左侧导航栏上选择 Project Files/app/libs/agora-rtc-sdk.jar 文件,右键单击,在下拉菜单中选择 add as a library。

创建用户界面

根据实时音视频互动的场景需要,为你的项目创建两个视图框,分别用于展示本地视频和远端视频。如下图所示:

复制以下代码到 /app/src/main/res/layout/activity_main.xml 文件中替换原有内容,即可快速创建场景所需的用户界面。

实现步骤

本小节介绍如何实现一个实时音视频互动 App。你可以先复制完整的示例代码到你的项目中,快速体验实时音视频互动的基础功能,再按照实现步骤了解核心 API 调用。

下图展示了使用声网 RTC SDK 实现音视频互动的基本流程:

下面列出了一段实现实时互动基本流程的完整代码以供参考。复制以下代码到 /app/src/main/java/com/example/<projectname>/MainActivity.java 文件中替换 package com.example.<projectname> 后的全部内容,即可快速体验实时互动基础功能。

信息

在 appId、token 和 channelName 字段中传入你在控制台获取到的 App ID、临时 Token,以及生成临时 Token 时填入的频道名。

处理权限请求

本小节介绍如何导入 Android 相关的类并获取 Android 设备的摄像头、录音等权限。

  1. 导入 Android 相关的类

    Java
    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.view.SurfaceView;
    import android.widget.FrameLayout;
    import android.widget.Toast;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;
  2. 获取 Android 权限

    启动应用程序时,检查是否已在 App 中授予了实现实时互动所需的权限。

    Java
    private static final int PERMISSION_REQ_ID = 22;
    
    // 获取体验实时音视频互动所需的录音、摄像头等权限
    private String[] getRequiredPermissions(){
        // 判断 targetSDKVersion 31 及以上时所需的权限
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
            return new String[]{
                    Manifest.permission.RECORD_AUDIO, // 录音权限
                    Manifest.permission.CAMERA, // 摄像头权限
                    Manifest.permission.READ_PHONE_STATE, // 读取电话状态权限
                    Manifest.permission.BLUETOOTH_CONNECT // 蓝牙连接权限
            };
        } else {
            return new String[]{
                    Manifest.permission.RECORD_AUDIO,
                    Manifest.permission.CAMERA
            };
        }
    }
    
    private boolean checkPermissions() {
        for (String permission : getRequiredPermissions()) {
            int permissionCheck = ContextCompat.checkSelfPermission(this, permission);
            if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

导入声网相关的类

导入声网 RTC SDK 相关的类和接口:

Java
import io.agora.rtc2.ChannelMediaOptions;
import io.agora.rtc2.Constants;
import io.agora.rtc2.IRtcEngineEventHandler;
import io.agora.rtc2.RtcEngine;
import io.agora.rtc2.RtcEngineConfig;
import io.agora.rtc2.video.VideoCanvas;

定义 App ID 和 Token

传入从声网控制台获取的 App ID、临时 Token,以及生成临时 Token 时填入的频道名,用于后续初始化引擎和加入频道。

Java
// 填写声网控制台中获取的 App ID
private String appId = "<#Your App ID#>";
// 填写频道名
private String channelName = "<#Your channel name#>";
// 填写声网控制台中生成的临时 Token
private String token = "<#Your Token#>";

初始化引擎

调用 create [2/2] 方法初始化 RtcEngine。

注意

在初始化 SDK 前,需确保终端用户已经充分了解并同意相关的隐私政策。

Java
private RtcEngine mRtcEngine;

private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
    ...
};

// 创建 RtcEngineConfig 对象,并进行配置
RtcEngineConfig config = new RtcEngineConfig();
config.mContext = getBaseContext();
config.mAppId = appId;
config.mEventHandler = mRtcEventHandler;
// 创建并初始化 RtcEngine
mRtcEngine = RtcEngine.create(config);

启用视频模块

按照以下步骤启用视频模块:

  1. 调用 enableVideo 方法,启用视频模块。
  2. 调用 setupLocalVideo 方法初始化本地视图,同时设置本地的视频显示属性。
  3. 调用 startPreview 方法,开启本地视频预览。
Java
// 启用视频模块
mRtcEngine.enableVideo();

// 创建一个 SurfaceView 对象,并将其作为 FrameLayout 的子对象
FrameLayout container = findViewById(R.id.local_video_view_container);
SurfaceView surfaceView = new SurfaceView (getBaseContext());
container.addView(surfaceView);
// 将 SurfaceView 对象传入声网实时互动 SDK,设置本地视图
mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, 0));

// 开启本地预览
mRtcEngine.startPreview();

加入频道并发布音视频流

调用 joinChannel [2/2] 加入频道。在 ChannelMediaOptions 中进行如下配置:

  • 设置频道场景为 BROADCASTING (直播场景) 并设置用户角色设置为 BROADCASTER (主播) 或 AUDIENCE (观众)。
  • 将 publishMicrophoneTrack 和 publishCameraTrack 设置为 true,发布麦克风采集的音频和摄像头采集的视频。
  • 将 autoSubscribeAudio 和 autoSubscribeVideo 设置为 true,自动订阅所有音视频流。
Java
// 创建 ChannelMediaOptions 对象,并进行配置
ChannelMediaOptions options = new ChannelMediaOptions();
// 设置用户角色为 BROADCASTER (主播) 或 AUDIENCE (观众)
options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER;
// 设置频道场景为 BROADCASTING (直播场景)
options.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING;
// 发布麦克风采集的音频
options.publishMicrophoneTrack = true;
// 发布摄像头采集的视频
options.publishCameraTrack = true;
// 自动订阅所有音频流
options.autoSubscribeAudio = true;
// 自动订阅所有视频流
options.autoSubscribeVideo = true;
// 使用临时 Token 和频道名加入频道,uid 为 0 表示引擎内部随机生成用户名
// 成功后会触发 onJoinChannelSuccess 回调
mRtcEngine.joinChannel(token, channelName, 0, options);

设置远端视图

调用 setupRemoteVideo 方法初始化远端用户视图,同时设置远端用户的视图在本地显示属性。你可以通过 onUserJoined 回调获取远端用户的 uid。

Java
private void setupRemoteVideo(int uid) {
    FrameLayout container = findViewById(R.id.remote_video_view_container);
    SurfaceView surfaceView = new SurfaceView (getBaseContext());
    surfaceView.setZOrderMediaOverlay(true);
    container.addView(surfaceView);
    // 将 SurfaceView 对象传入声网实时互动 SDK,设置远端视图
    mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, uid));
}

实现常用回调

根据使用场景,定义必要的回调。以下示例代码展示如何实现 onJoinChannelSuccess、 onUserJoined 和 onUserOffline 回调。

Java
// 成功加入频道回调
@Override
public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
    super.onJoinChannelSuccess(channel, uid, elapsed);
    runOnUiThread(() -> {
        Toast.makeText(MainActivity.this, "Join channel success", Toast.LENGTH_SHORT).show();
    });
}

// 远端用户或主播加入当前频道回调
@Override
public void onUserJoined(int uid, int elapsed) {
    runOnUiThread(() -> {
        // 当远端用户加入频道后,显示指定 uid 的远端视频流
        setupRemoteVideo(uid);
    });
}

// 远端用户或主播离开当前频道回调
@Override
public void onUserOffline(int uid, int reason) {
    super.onUserOffline(uid, reason);
    runOnUiThread(() -> {
        Toast.makeText(MainActivity.this, "User offline: " + uid, Toast.LENGTH_SHORT).show();
    });
}

开始音视频互动

在 onCreate 中调用一系列方法加载界面布局、检查 App 是否获取实时互动所需权限,并加入频道开始音视频互动。

Java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 如果已经授权,则初始化 RtcEngine 并加入频道
    if (checkPermissions()) {
        initializeAndJoinChannel();
    } else {
        ActivityCompat.requestPermissions(this, getRequiredPermissions(), PERMISSION_REQ_ID);
    }
}

结束音视频互动

按照以下步骤结束音视频互动:

  1. 调用 stopPreview 停止视频预览。

  2. 调用 leaveChannel 离开当前频道,释放所有会话相关的资源。

  3. 调用 destroy 销毁引擎,并释放声网 SDK 中使用的所有资源。

    注意

    • 该方法为同步调用。需要等待引擎资源释放后才能执行其他操作,因此建议在子线程中调用该方法,避免主线程阻塞。
      • 调用 destroy 后,你将无法再使用 SDK 的所有方法和回调。如需再次使用实时音视频互动功能,你必须重新创建一个新的引擎。详见初始化引擎。
    Java
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mRtcEngine != null) {
            // 停止本地视频预览
            mRtcEngine.stopPreview();
            // 离开频道
            mRtcEngine.leaveChannel();
            mRtcEngine = null;
            // 销毁引擎
            RtcEngine.destroy();
        }
    }

调试 App

按照以下步骤测试直播 App:

  1. 开启 Android 设备的开发者选项,打开 USB 调试,通过 USB 连接线将 Android 设备接入电脑,并在 Android 设备选项中勾选你的 Android 设备。

  2. 在 Android Studio 中,点击 同步 Gradle 项目 (Sync Project with Gradle Files) 进行 Gradle 同步。

  3. 待同步成功后,点击 运行 (Run 'app') 开始编译。片刻后,App 便会安装到你的 Android 设备上。

  4. 启动 App,授予录音和摄像头权限,如果你将用户角色设置为主播,便会在本地视图中看到自己。

  5. 使用第二台 Android 设备,重复以上步骤,在该设备上安装 App、打开 App 加入频道,观察测试结果:

    • 如果两台设备均作为主播加入频道,则可以看到对方并且听到对方的声音。
    • 如果两台设备分别作为主播和观众加入,则主播可以在本地视频窗口看到自己;观众可以在远端视频窗口看到主播、并听到主播的声音。

后续步骤

在完成音视频互动后,你可以阅读以下文档进一步了解:

  • 本文的示例使用了临时 Token 加入频道。在测试或生产环境中,为保证通信安全,声网推荐从服务器中获取 Token,详情请参考使用 Token 鉴权。
  • 如果你想要实现极速直播场景,可以在实时音视频互动的基础上,通过修改观众端的延时级别为低延时 (AUDIENCE_LATENCY_LEVEL_LOW_LATENCY) 实现。详见实现极速直播。

参考信息

示例项目

声网提供了开源的实时音视频互动示例项目供你参考,你可以前往下载或查看其中的源代码。

常见问题

相关文档