【WebRTC】Android SDK使用教学
文章目录
- 前言
- PeerConnectionFactory
- PeerConnection
前言
最近在学习WebRTC的时候,发现只有JavaScript的API文档,找了很久没有找到Android相关的API文档,所以通过此片文章记录下在Android应用层如何使用WebRTC
本篇文章结合:【WebRTC】适合新手宝宝的WebRTC入门教学一起食用更佳
PeerConnectionFactory
负责管理和创建WebRTC所需组件,例如:音视频轨道、PeerConnection,是WebRTC使用的起点
// 1. 初始化Factory,此步骤用于初始化日志、加载JniLib、对Jni进行初始化
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(WebRtcApp.instance).createInitializationOptions()
)// 2. 创建factory实例,通过builder可以设置编解码器工厂、AudioDeviceModule(音频设备管理模块)
peerConnectionFactory = PeerConnectionFactory.builder().setOptions(PeerConnectionFactory.Options()).setAudioDeviceModule(audioDeviceModule).setVideoDecoderFactory(defaultDecoder).setVideoEncoderFactory(defaultEncoder).createPeerConnectionFactory()// 3. 创建peerConnection、音视频轨道等
localPeerClient = peerConnectionFactory.createPeerConnection()
videoSource = peerConnectionFactory.createVideoSource(false)
localVideoTrack = peerConnectionFactory.createVideoTrack(WebRtcConstant.VideoTrackID, videoSource)
PeerConnection
这是WebRTC API中最重要的类,负责点对点连接的建立,音视频推流等
1. PeerConnection.RTCConfiguration
WebRTC连接参数,必须通过ICE服务器(PeerConnection.IceServer)列表进行构建
val rtcConfig = PeerConnection.RTCConfiguration(peerIceServers)
rtcConfig.apply {bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLEsdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLANcontinualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLYkeyType = PeerConnection.KeyType.ECDSArtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIREtcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLEDsuspendBelowMinBitrate = true
}
2. 交换SDP
PeerConnection提供了SDP Offer的创建和发送相关方法
// 1. 创建offer
localPeerClient.createOffer(object : KinesisVideoSdpObserver() {override fun onCreateSuccess(sessionDescription: SessionDescription) {// 1.1 创建offer成功回调super.onCreateSuccess(sessionDescription)// 2. 创建成功后需要将offer设置为LocalDescriptionlocalPeerClient.setLocalDescription(KinesisVideoSdpObserver(), sessionDescription)// 3. 此时应该通过信令服务器将offer发送给远端}}, AwsEngine.getSdpMediaConstraints())// 4. 当收到远端响应的answer时,设置为RemoteDescription
localPeerClient.setRemoteDescription(KinesisVideoSdpObserver(), sdpAnswer)// 5. 当收到远端的offer时,此时先设置RemoteDescription然后需要响应answer
localPeerClient.createAnswer(object : KinesisVideoSdpObserver() {override fun onCreateSuccess(sessionDescription: SessionDescription) {// 5.1 创建answer成功super.onCreateSuccess(sessionDescription)// 5.2 设置为LocalDescriptionit.setLocalDescription(KinesisVideoSdpObserver(), sessionDescription)// 5.3 通过信令服务器发送回远端}}, MediaConstraints())
}
3. 设置ICE候选地址对
ICE候选地址对的来源有两个,一个是由localPeerClient在创建后根据PeerConnection.IceServer返回的,这些地址需要同发送给远端。另一个来源是远端设备,远端设备在与ICE通信后会得到它的候选地址对,此时远端会通过信令服务器通知本设备。
peerConnectionFactory.createPeerConnection(rtcConfig,object : KinesisVideoPeerConnection() {override fun onIceCandidate(iceCandidate: IceCandidate) {// 1. 由WebRTC自动探测出的候选地址对回调super.onIceCandidate(iceCandidate)// 1.1 通过信令服务器告诉远端signalingClient?.sendIceCandidate(message)}}
)// 2. 来自信令服务器的回调
override fun onReceiverIceCandidate(event: Event) {// 2.1 收到远端的候选地址对后,添加到本地的WebRTC中,等待WebRTC自行尝试连接val iceCandidate = Event.parseIceCandidate(event)PeerConnection.addIceCandidate(iceCandidate)
}
4. 添加本地音视频轨道
在WebRTC建立连接后,此时远端的数据会通过回调传来,如果本机需要向远端推流,此时只需要设置音视频轨道即可
// 1. 创建一个空流,需要手动为期添加音轨和视频轨
stream = peerConnectionFactory.createLocalMediaStream(WebRtcConstant.LOCAL_MEDIA_STREAM_LABEL)// 2. 创建视频源,默认创建的源是没有数据的,通常要与摄像头、或自定义数据源进行绑定
videoSource = peerConnectionFactory.createVideoSource(false)// 3. 创建视频轨道,可以绑定到 UI 组件(如本地预览)或添加到 PeerConnection。
// 例如将视频轨道绑定到本地预览视图:localVideoTrack.addSink(localVideoView)
localVideoTrack = peerConnectionFactory.createVideoTrack(WebRtcConstant.VideoTrackID, videoSource)// 4. 向流添加视频轨
stream.addTrack(localVideoTrack)
// 5. 将视频流交至WebRTC处理
localPeerClient?.addTrack(stream!!.videoTracks[0], listOf(stream!!.id))
ps:为什么要设计将数据源和数据轨道分开来
- 解藕数据源和传输的逻辑,数据源负责数据的采集和生成,数据轨道负责数据的传输
- 可实现多个数据轨道共享同一个数据源,避免重复采集
5. 开启数据通道
WebRTC不仅提供数据流的传输,还能提供数据报文传输,只需要打开数据通道
// 1. 创建数据通道
localDataChannel = localPeerClient?.createDataChannel("data-channel-of-${connectParameter?.clientId}", DataChannel.Init())
// 2. 注册消息监听
localDataChannel?.registerObserver(object :DataChannel.Observer{override fun onBufferedAmountChange(previousAmount: Long) {}override fun onStateChange() {}override fun onMessage(buffer: DataChannel.Buffer) {// 2.1 远端消息到来时回调val byteArray = ByteArray(buffer.data.remaining())buffer.data.get(byteArray)val messageStr = String(byteArray, Charsets.UTF_8)}
})
// 3. 向远端发送消息
localDataChannel?.send(DataChannel.Buffer(ByteBuffer.wrap(content.toByteArray(Charset.defaultCharset())),false)
)
相关文章:
【WebRTC】Android SDK使用教学
文章目录 前言PeerConnectionFactoryPeerConnection 前言 最近在学习WebRTC的时候,发现只有JavaScript的API文档,找了很久没有找到Android相关的API文档,所以通过此片文章记录下在Android应用层如何使用WebRTC 本篇文章结合:【W…...
基于单片机的智能晾衣控制系统的设计与实现
摘要:本文是以 AT89C52 单片机为核心来实现智能晾衣控制系统。在这个系统中,雨水检测传感器是用来检测出雨的,而控制器将检测信号的变换,根据变换后的信号自动驱动直流电机将被风干 的棒收回,以便随时控制直流电机来实现晾衣;在光敏模块中检测昼夜的环境,自动控制晾衣杆…...

多人聊天室 NIO模型实现
NIO编程模型 Selector监听客户端不同的zhuangtai不同客户端触发不同的状态后,交由相应的handles处理Selector和对应的处理handles都是在同一线程上实现的 I/O多路复用 在Java中,I/O多路复用是一种技术,它允许单个线程处理多个输入/输出&…...

三、使用 Maven:命令行环境
文章目录 1. 第一节 实验一:根据坐标创建 Maven 工程1.1 Maven 核心概念:坐标1.2 实验操作1.3 Maven核心概念:POM1.4 Maven核心概念:约定的目录结构 2. 实验二:在 Maven 工程中编写代码2.1 主体程序2.2 测试程序 3. 执…...

Blender导入下载好的fbx模型像的骨骼像针戳/像刺猬
为什么我下载下来的骨骼模型和我自己绑定的模型骨骼朝向完全不一样 左边是下载的模型 右边是我自己绑定的模型 左边的模型刚刚感觉都是像针一样往外戳的,像刺猬一样那种。 解决方法勾选自动骨骼坐标系...
如何高效搭建智能BI数据分析系统
作为当今信息化时代,数据资产已经成为企业最为核心倚重的,自然企业也就面临来自于对内部这些数据的处理和分析。如何在大批量的数据当中提取有用信息,帮助企业做出智慧决策,是不少企业面临的问题。作为国内知名的BI数据分析系统服…...
第 6 章 Java 并发包中锁原理剖析Part one
目录 6.1 LockSupport 工具类 6.2 独占锁 ReentrantLock 的原理 获取锁 1.void lock() 方法 2.void lockInterruptibly() 方法 3.boolean tryLock() 方法 4.boolean tryLock(long timeout, TimeUnit unit) 方法 释放锁 6.1 Lo…...
使用 Canvas 绘制一个镂空的圆形区域
如果要实现一个类似人脸识别的界面,要求使用 canvas 进行绘制,中间镂空透明区域,背景是白色的画布。 技术方案: 首先,使用 canvas 绘制一个白色画布其次,使用 context.globalCompositeOperation 合成属性进…...

【Notepad++】---设置背景为护眼色(豆沙绿)最新最详细
在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。 【Notepad】---设置背景为护眼色…...

2024 数学建模国一经验分享
2024 数学建模国一经验分享 背景:武汉某211,专业:计算机科学 心血来潮,就从学习和组队两个方面指点下后来者,帮新人避坑吧 2024年我在数学建模比赛中获得了国一(教练说论文的分数是湖北省B组第一࿰…...
安全见闻2
安全见闻,犹如一座庞大而深邃的知识宝库,其中涵盖了形形色色的网络安全知识与错综复杂的网络技术体系。在当今数字化时代,这些领域的重要性不言而喻,它们不仅关乎个人信息的保护与隐私安全,更是支撑着整个互联网世界以…...
Web游戏开发指南:在 Phaser.js 中读取和管理游戏手柄输入
前言 Phaser.js 是一个广受欢迎的 HTML5 游戏框架,为开发者提供了创建跨平台 2D 游戏的强大工具。在现代游戏开发中,支持游戏手柄已成为提升玩家体验的重要方面。本文将详细介绍如何在 Phaser.js 中监听和处理游戏手柄的输入,帮助开发者为他…...

代码随想录32 动态规划理论基础,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯。
1.动态规划理论基础 动态规划刷题大纲 什么是动态规划 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的…...

记录一个Flutter 3.24单元测试点击事件bug
哈喽,我是老刘 这两天发现一个Flutter 3.24版本的单元测试的一个小bug,提醒大家注意一下。 老刘自己写代码十多年了,写Flutter也6年多了,没想到前两天在一个小小的BottomNavigationBar 组件上翻了车。 给大家分享一下事件的经过。…...
使用Python将 word文档转pdf文档
第一步:我们需要导入支持包 >pip install pywin32 如果下载速度比较慢的话,可以考虑使用国内镜像源。 第二步:我们需要导入文件,这里采用 input,用户填入路径后,直接获取路径下的word文档,实现批量转换…...

基于C#+SQLite开发数据库应用的示例
SQLite数据库,小巧但功能强大;并且是基于文件型的数据库,驱动库就是一个dll文件,有些开发工具 甚至不需要带这个dll,比如用Delphi开发,用一些三方组件;数据库也是一个文件,虽然是个文…...

Vue基本语法
Options API 选项式/配置式api 需要在script中的export default一个对象对象中可以包含data、method、components等keydata是数据,数据必须是一个方法(如果是对象,会导致多组件的时候,数据互相影响,因为对象赋值后&…...
芯片发展史
芯片的发展史可分为几个重要的阶段,从早期的真空管到现代的集成电路,反映了技术进步和创新的历程: 1. 真空管时代 (1904 - 1950年代) 真空管是20世纪初的电子元件,用于放大信号和开关,广泛应用在早期的收音机、电视机…...

我的知识图谱和Neo4j数据库的使用
知识图谱概述 知识图谱的含义 RDF与RDFS RDF(Resource Description Framework,资源描述框架)和RDFS(RDF Schema,RDF模式)是构建知识图谱的基础技术之一。它们提供了一种标准的方式来表示信息,…...

ASP.NET CORE API 解决跨域问题
环境 vs2022 .net 8 创建ASP.net Core API项目 配置跨域 编写ApiController 启动项目 得到服务器运行的 地址 在Hbuiler中创建web项目,编写代码 【运行】-【运行到浏览器】-选择一个浏览器,查看结果 正常显示 问题 如果允许所有源访问,有安全风险方…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...