背景簡介
WebRTC被譽為是web長期開源開發(fā)的一個新啟元辨泳,是近年來web開發(fā)的最重要創(chuàng)新顾翼。WebRTC允許Web開發(fā)者在其web應(yīng)用中添加視頻聊天或者點對點數(shù)據(jù)傳輸合愈,不需要復(fù)雜的代碼或者昂貴的配置颅崩。目前支持Chrome、Firefox和Opera吃引,后續(xù)會支持更多的瀏覽器筹陵,它有能力達(dá)到數(shù)十億的設(shè)備刽锤。
然而,WebRTC一直被誤解為僅適合于瀏覽器朦佩。事實上并思,WebRTC最重要的一個特征是允許本地和web應(yīng)用間的互操作,很少有人使用到這個特性语稠。
所以自然Android應(yīng)用也可以植入WebRTC宋彼。好處是什么?簡單來說就是你可以用很簡潔的代碼仙畦,在手機上實現(xiàn)點對點的視頻聊天或者數(shù)據(jù)傳輸输涕,點對點!點對點慨畸!點對點莱坎!重要的事情說三遍。
項目準(zhǔn)備
信令服務(wù)器代碼:https://github.com/matthewYang92/WebRtcServer(代碼改自ProjectRTC)
- 安裝Node.js
- 進入項目根目錄寸士,命令行:npm install
- 命令行:node app.js
- 打開瀏覽器輸入127.0.0.1:3000檐什,見到WebRtcServer標(biāo)題,服務(wù)器ready
客戶端代碼:https://github.com/matthewYang92/WebRtcAndroidClient(代碼參考AndroidRTC項目)
- 下載后直接AndroidStudio打開
- 將
WebRtcClient.java
類中的mSocketAddress
變量改成你服務(wù)器的ip端口3000 - 安裝后啟動App碉京,如果服務(wù)器log顯示-- xxxxx joined --證明客戶端已連上服務(wù)器
- 至少兩個客戶端連接到服務(wù)器之后厢汹,其中一端點擊init開始連接
如果你已經(jīng)成功跑通了Demo螟深,那么恭喜你已經(jīng)成功了一半谐宙,接下來我們分析下實現(xiàn)流程。
實現(xiàn)流程
一界弧、添加WebRTC庫依賴
compile 'org.webrtc:google-webrtc:1.0.+'
二凡蜻、初始化核心類PeerConnectionFactory
PeerConnectionFactory.initialize(PeerConnectionFactory
.InitializationOptions
.builder(this)
.createInitializationOptions());
三、創(chuàng)建PeerConnection對象
peerConnection = factory.createPeerConnection(
iceServers, //ICE服務(wù)器列表
constraints, //MediaConstraints
this); //Context
四垢箕、建立P2P連接通道
WebRTC是基于P2P的划栓,但在端與端之間的連接通道還沒建立起來之前,我們需要通過一個信令服務(wù)器為端與端之間傳遞信令建立通道条获。信令服務(wù)器要做的東西很簡單忠荞,就是將一端的信息透傳給另一端,步驟如下(以Demo為例):我們啟動A端與B端帅掘,通過SocketIO連接到信令服務(wù)器委煤,我們以A作為發(fā)送端,B為響應(yīng)端修档。
信令交換
- A向服務(wù)器發(fā)出init請求
- 服務(wù)器將A的init請求轉(zhuǎn)發(fā)給連接上服務(wù)器的其他端
- B收到init請求后碧绞,調(diào)用
peerConnection.createOffer()
方法創(chuàng)建一個包含SDP的offer信令 - offer信令創(chuàng)建成功后會調(diào)用
SdpObserver
監(jiān)聽中的onCreateSuccess()
響應(yīng)函數(shù),在此處B通過peerConnection.setLocalDescription()
方法將SDP賦予自己的PeerConnection
對象吱窝,同時將offer信令發(fā)送給服務(wù)器 - 服務(wù)器將offer信令轉(zhuǎn)發(fā)給A端
- A收到offer信令后讥邻,調(diào)用
peerConnection.setRemoteDescription()
方法將B發(fā)過來的SDP賦予自己的PeerConnection
對象迫靖,并調(diào)用peerConnection.createAnswer()
方法創(chuàng)建一個answer信令 - answer信令創(chuàng)建成功后同樣會調(diào)用
SdpObserver
監(jiān)聽中的onCreateSuccess()
響應(yīng)函數(shù),在此處A同樣通過peerConnection.setLocalDescription
方法將SDP賦予自己的PeerConnection
對象兴使,同時將answer信令發(fā)送給服務(wù)器 - 服務(wù)器將answer信令轉(zhuǎn)發(fā)給B端
- B收到A的answer信令后系宜,利用
peerConnection.setRemoteDescription()
方法將A發(fā)過來的SDP賦予自己的PeerConnection
對象
設(shè)置Candidate
-
PeerConnection.Observer
監(jiān)聽會調(diào)用onIceCandidate()
響應(yīng)函數(shù)并提供IceCandidate
對象。然后將IceCandidate
對象組成candidate信令發(fā)送給服務(wù)器 - 服務(wù)器將candidate信令轉(zhuǎn)發(fā)給連接上服務(wù)器的其他端
- 收到candidate信令后調(diào)用
peerConnection.addIceCandidate()
將IceCandidate
賦予自己的PeerConnection
對象
至此Peer-to-Peer的連接已經(jīng)建立起來了
五鲫惶、使用DataChannel收發(fā)信息
-
初始化DataChannel對象
/* DataChannel.Init 可配參數(shù)說明: ordered:是否保證順序傳輸蜈首; maxRetransmitTimeMs:重傳允許的最長時間; maxRetransmits:重傳允許的最大次數(shù)欠母; */ DataChannel.Init init = new DataChannel.Init(); dataChannel = peerConnection.createDataChannel("dataChannel", init);
-
在
onDataChannel()
回調(diào)中注冊消息回調(diào)dataChannel.registerObserver(this);
-
發(fā)送消息
byte[] msg = message.getBytes(); DataChannel.Buffer buffer = new DataChannel.Buffer( ByteBuffer.wrap(msg), false); dataChannel.send(buffer);
-
onMessage()
回調(diào)收消息ByteBuffer data = buffer.data; byte[] bytes = new byte[data.capacity()]; data.get(bytes); String msg = new String(bytes);
六欢策、關(guān)于ICE服務(wù)
(以下內(nèi)容引用自http://blog.csdn.net/youmingyu/article/details/53192714,博主的文章對我?guī)椭级嗌吞剩浅8兄x)
如果在局域網(wǎng)內(nèi)踩寇,信令交換后就已經(jīng)可以傳遞媒體流了,但如果雙方不在同一個局域網(wǎng)六水,就需要進行NAT/防火墻穿透(我是在局域網(wǎng)下測試的俺孙,沒有穿透,但還是把這方面內(nèi)容介紹下)掷贾。
WebRTC使用ICE框架來保證穿透睛榄。ICE全名叫交互式連接建立(Interactive Connectivity Establishment),一種綜合性的NAT/FW穿越技術(shù),它是一種框架想帅,可以整合各種NAT/FW穿越技術(shù)如STUN场靴、TURN(Traversal Using Relay NAT 中繼NAT實現(xiàn)的穿透)。ICE會先使用STUN港准,嘗試建立一個基于UDP的連接旨剥,如果失敗了,就會去TCP(先嘗試HTTP浅缸,然后嘗試HTTPS)轨帜,如果依舊失敗ICE就會使用一個中繼的TURN服務(wù)器。使用STUN服務(wù)器穿透的結(jié)構(gòu)如下:
我們可以使用Google的stun服務(wù)器:stun:stun.l.google.com:19302(Google嘛衩椒,翻墻你懂得蚌父,當(dāng)然如果有精力可以自己搭建一個stun服務(wù)器),那么我們怎么把這個地址告訴WebRTC呢毛萌,還記得之前的iceServers嗎苟弛,就是在創(chuàng)建PeerConnection對象的時候需要的參數(shù),iceServers里面存放的就是進行穿透地址變換的服務(wù)器地址朝聋,添加方法如下(保險起見可以多添加幾個服務(wù)器地址嗡午,如果有的話):
iceServers.add(new PeerConnection.IceServer("stun:stun.l.google.com:19302"));
參考
官網(wǎng)
Android之WebRTC介紹
WebRTC的Android2Android實現(xiàn)
NAT- STUN和TURN簡介