初次接触webrtc,尝试web端与android端通信,以及进一步实现android间通信
准备:在github上下载webrtc在android端的源码(另需下载node.js服务端源码,在该网站下有引导——https://github.com/pchab/AndroidRTC)
源码:projectRTC——服务端,也可作为web端 需在终端输入 node app.js(或者npm start,这种方法无法关闭,服务器始终运行)
androidRTC——android端。其中有两个部分:app为主界面,webrtc-client为工具类module
WebRTC Android端的大体实现过程如下:
- 连接服务器,并通过服务器打通两个客户端的网络通道
- 从摄像头和麦克风获取媒体流
- 将本地媒体流通过网络通道传送给对方的客户端
- 渲染播放接收到的媒体流
建立连接通道时我们需要在WebRTC两个客户端之间进行一些信令交换,我们以A作为发起端,B作为响应端(A call B,假设服务器和A、B已经连接好,并且只提供转发功能,PeerConnection对象为pc ):
- A向B发出一个“init”请求
- B收到后“init”请求后,调用
pc.createOffer()
方法创建一个包含SDP描述符(包含媒体信息,如分辨率、编解码能力等)的offer信令。 - offer信令创建成功后会调用SdpObserver监听中的
onCreateSuccess()
响应函数,在这里B会通过pc.setLocalDescription
将offer信令(SDP描述符)赋给自己的PC对象,同时将offer信令发送给A 。 - A收到B的offer信令后,利用
pc.setRemoteDescription()
方法将B的SDP描述赋给A的PC对象。 - A在
onCreateSuccess()
监听响应函数中调用pc.setLocalDescription
将answer信令(SDP描述符)赋给自己的PC对象,同时将answer信令发送给B 。 - B收到A的answer信令后,利用
pc.setRemoteDescription()
方法将A的SDP描述赋给B的PC对象。
至此,A、B之间就完成里了信令交换。
通过ICE框架穿透NAT/防火墙:
(如果在局域网内,信令交换后就已经可以传递媒体流,但如果双方不在同一个局域网,就需要进行NAT/防火墙穿透,下面是NAT/防火墙穿透的介绍)
WebRTC使用ICE框架来保证穿透。ICE全名叫交互式连接建立(Interactive Connectivity Establishment),一种综合性的NAT/FW穿越技术,它是一种框架,可以整合各种NAT/FW穿越技术如STUN、TURN(Traversal Using Relay NAT 中继NAT实现的穿透)。ICE会先使用STUN,尝试建立一个基于UDP的连接,如果失败了,就会去TCP(先尝试HTTP,然后尝试HTTPS),如果依旧失败ICE就会使用一个中继的TURN服务器。
stun服务器地址也需要通过信令交换,同样以A、B客户端为例过程如下:
- A、B分别创建PC实例pc(配置了穿透服务器地址) 。
- 当网络候选可用时,PeerConnection.Observer监听会调用
onIceCandidate()
响应函数并提供IceCandidate(里面包含穿透所需的信息)的对象。在这里,我们可以让A、B将IceCandidate对象的内容发送给对方。 - A、B收到对方发来的candidate信令后,利用
pc.addIceCandidate()
方法将穿透信息赋给各自的PeerConnection对象。
final Intent intent = getIntent();
final String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(action)) {
final List<String> segments = intent.getData().getPathSegments();
callerId = segments.get(0);
}
这些代码的目的是得到我们的callerId,但是得到的callerId通过后面的onCallReady方法中法中的实现,发现其是null,既然是null完全可以不要这几行代码,不太明
白为什么。
服务端:因为第一次接触node.js 对服务端具体的实现还处于萌新状态
另外,在socketHandler.js里,源代码为client.emit('id',client.id)这行代码不太理解,我总以为它的意思是服务端将客户自己的id发给客户。