> 技术文档 > Android实现WebRTC的android端互连(附带源码)_android webrtc

Android实现WebRTC的android端互连(附带源码)_android webrtc


一、项目介绍

1. 背景与意义

随着移动端实时通讯(RTC)需求的爆炸式增长,基于 WebRTC 的点对点(P2P)视频和音频通话已成为几乎所有现代社交、直播、远程协作应用的核心功能。在 Android 平台上直接使用 WebRTC 原生 API 能最大化定制性和性能,但学习曲线陡峭、配置复杂。本项目通过手把手示例,教你在 Android 上从零开始:

  1. 集成 Google WebRTC 原生库

  2. 建立信令通道(使用 WebSocket)

  3. 完成两台 Android 设备之间互连

  4. 传输并渲染实时视频流与音频流

  5. 管理 ICE 候选、SDP 协商、网络变化

  6. 处理会话断开与重连

  7. 封装复用模块,支持多房间、多对多通话

全文超过一万字,所有代码整合到一个代码块中,用注释区分不同文件,便于复制。

2. 功能需求

  • 双端互连:两部 Android 设备加入同一房间,相互看到对方摄像头画面并听到对方音频

  • 信令服务:基于 WebSocket 进行 SDP 与 ICE 候选交换

  • 视频渲染:SurfaceViewRenderer 渲染本地与远端

  • 网络自适应:处理网络切换与重连

  • UI 交互:开始/结束通话、切换前后摄、静音、视频开关

  • 日志与统计:展示通话时长、丢包、码率等信息


二、相关知识

  1. WebRTC 核心组件

    • PeerConnectionFactory:工厂,用于创建音视频捕获器、编码器与 PeerConnection

    • PeerConnection:负责底层 ICE 协商、NAT 穿透与媒体传输

    • VideoCapturer + VideoTrack:采集摄像头并编码发送

    • SurfaceViewRenderer:渲染远端与本地视频

    • AudioTrack:采集与播放音频

  2. 信令协议

    • WebRTC 本身不包含信令,需要自定义。常用 WebSocket、Socket.IO、RESTful+Long Polling 等

  3. ICE 与 STUN/TURN

    • IceServer 列表包含 STUN(候选发现)与 TURN(中继)服务器

    • 根据环境添加公有或自建 STUN/TURN

  4. SDP 协商流程

    • Caller 创建 Offer,Caller SetLocalDescription → 发送 Offer → Callee SetRemoteDescription → Callee CreateAnswer → Callee SetLocalDescription → 发送 Answer → Caller SetRemoteDescription

    • 双方收集与交换 ICE 候选

  5. Android 与 WebRTC 打包

    • 可以从 Google Maven(org.webrtc:google-webrtc:VERSION)拉取,也可用官方 C++ 源码自行编译

  6. 多线程与 Looper

    • WebRTC 在内部使用 EglBase.ContextSurfaceViewRenderer 要在 UI 线程操作,协商和 I/O 可在后台线程

  7. 性能与电量

    • 建议使用硬件编码(默认),并在低带宽场景下动态适应分辨率和帧率


三、环境与依赖

// app/build.gradleplugins { id \'com.android.application\' id \'kotlin-android\'}android { compileSdk 34 defaultConfig { applicationId \"com.example.webrtcdemo\" minSdk 21 targetSdk 34 } packagingOptions { pickFirst \'lib/armeabi-v7a/libjingle_peerconnection_so.so\' pickFirst \'lib/arm64-v8a/libjingle_peerconnection_so.so\' }}dependencies { implementation \"androidx.appcompat:appcompat:1.6.1\" implementation \"androidx.constraintlayout:constraintlayout:2.1.4\" implementation \"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4\" // WebRTC 原生库 implementation \'org.webrtc:google-webrtc:1.0.32006\' // WebSocket 客户端 implementation \'com.squareup.okhttp3:okhttp:4.10.0\'}

四、实现思路与架构

  1. 信令模块 SignalClient

    • WebSocket 连接服务器,封装 sendOffer(), sendAnswer(), sendIceCandidate()

    • 注册回调收到远端 SDP/ICE 后调用 onRemoteSessionReceived()

  2. PeerConnection 管理 RTCClient

    • 初始化 PeerConnectionFactory、创建本地流(摄像头+麦克风)

    • 创建 PeerConnection,添加本地 MediaStream,设置 PeerConnection.Observer

    • startCall()createOffer() → 发送 Offer

    • 接收到 Offer → onRemoteSessionReceived()createAnswer() → 发送 Answer

    • 交换 ICE 候选

  3. UI 层 MainActivity

    • 持有两个 SurfaceViewRenderer:本地与远端

    • 按钮触发呼叫/挂断、静音、摄像头切换

    • 显示通话时长与网络状态

  4. 生命周期管理

    • onCreate() 初始化,onDestroy() 释放资源

    • 退出通话时关闭 WebSocket 与 PeerConnection

  5. 网络重连

    • SignalClient 在 WebSocket 断开时自动重试

    • PeerConnection 在 ICE 失败时尝试重连接


五、整合代码

// =======================================================// 文件:AndroidManifest.xml// 描述:申请网络与摄像头权限// =======================================================           // =======================================================// 文件:res/layout/activity_main.xml// 描述:双 SurfaceViewRenderer 与控制按钮// =======================================================    

六、代码解读

  1. SignalClient

    • 基于 OkHttp WebSocket 实现信令交换,消息格式为 JSON,封装了 Offer/Answer/IceCandidate 三种类型。

  2. RTCClient

    • 初始化 PeerConnectionFactory 并创建本地视频轨道 VideoCapturerVideoTrackAudioTrack

    • 创建 PeerConnection 并添加冰候选与媒体流;

    • 提供 startCall()onRemoteOffer()onRemoteAnswer()onRemoteIceCandidate() 四个方法完成完整协商;

    • PeerConnection.Observer 回调中将远端流通过接口回调给 Activity;

  3. MainActivity

    • SurfaceViewRenderer 在 UI 线程初始化并绑定 EglBase;

    • 按钮事件:呼叫、挂断、静音、切换摄像头;

    • 本地轨道和远端轨道分别渲染到对应 SurfaceViewRenderer

  4. 摄像头捕获

    • 使用 Camera2Enumerator 枚举、优先选取前置摄像头;

    • 通过 SurfaceTextureHelper 管理采集线程;

  5. 切换摄像头

    • RTCClient 中调用 videoCapturer.switchCamera() 重建轨道并替换源;


七、性能与优化

  1. 网络适应:在 PeerConnection 创建约束时添加 googCpuOveruseDetection 等字段,自动调整码率与分辨率;

  2. 带宽管理:使用 setParameters() 动态调整视频编码码率;

  3. ICE 策略:自建 TURN 服务器,补齐 NAT 穿透;

  4. 日志与统计:注册 StatsObserver,定期调用 getStats() 获取丢包率、往返时延;

  5. 资源释放:Activity 销毁前调用 eglBase.release()peerConnection.close()factory.dispose()


八、项目总结与扩展思路

本文手把手演示了如何在 Android 上用原生 WebRTC API 实现两端点点对点音视频通话,涵盖信令、协商、编解码与渲染全流程,并封装成可复用的模块。接下来可进一步:

  • 多方通话(Mesh/SFU):使用媒体服务器(Medooze、Janus)管理多路流;

  • 数据通道:利用 WebRTC DataChannel 实现文本消息或文件传输;

  • 自定义编解码:切换到 H.265、VP9 或 AV1;

  • 再包装成 SDK:封装成独立库,提供更高层 API;


九、FAQ

  1. 信令服务器如何部署?

    • 最简单可用 Node.js + ws 库,示例请参考官方 samples;

  2. 如何支持前台推送 TURN?

    • 在 ICE 配置中添加 TURN 服务器信息并传入凭证;

  3. 为什么会出现黑屏?

    • 确认 addSink() 时机,必须在 SurfaceViewRenderer.init() 之后;

  4. 音视频不同步?

    • 检查采集帧率与编码帧率是否一致,开启 Factory.Options.enableInternalTracer 分析;

  5. 如何打包 SO?

    • 已在 Gradle 中指定 packagingOptions,确保 .so 被正确打入 APK;