Android
WebRTC

[webRTC for android vol4] 複数台接続

More than 1 year has passed since last update.

Android で複数台接続いきます。

成果物

https://github.com/nakadoribooks/webrtc-android/releases/tag/v0.0.4

↑ iOSとブラウザが相手。

環境

  • android studio 2.3.3
  • Nexus 5x android6.0.1

流れ

設計

IMG_4767.JPG

インタフェース

Wamp

WampInterface.java
enum Topic {

    Callme("com.nakadoribook.webrtc.[roomId].callme"),
    Close("com.nakadoribook.webrtc.[roomId].close"),
    Answer("com.nakadoribook.webrtc.[roomId].[userId].answer"),
    Offer("com.nakadoribook.webrtc.[roomId].[userId].offer"),
    Candidate("com.nakadoribook.webrtc.[roomId].[userId].candidate");

    private final String text;

    private Topic(final String text) {
        this.text = text;
    }

    public String getString() {
        return this.text;
    }
}

interface WampCallbacks {

    void onOpen();
    void onReceiveAnswer(String targetId, String sdp);
    void onReceiveOffer(String taretId, String sdp);
    void onIceCandidate(String targetId, String sdp, String sdpMid, int sdpMLineIndex);
    void onReceiveCallme(String targetId);
    void onCloseConnection(String targetId);

}

public interface WampInterface {

    void connect();
    void publishCallme();
    void publishOffer(String targetId, String sdp);
    void publishAnswer(String targetId, String sdp);
    void publishCandidate(String targetId, String candidate);

}

WebRTC

WebRTCInterface.java
interface WebRTCCallbacks{

    void onCreateOffer(String sdp);
    void onCreateAnswer(String sdp);
    void didReceiveRemoteStream(MediaStream mediaStream);
    void onIceCandidate(String sdp, String sdpMid, int sdpMLineIndex);

}

public interface WebRTCInterface {

    void createOffer();
    void receiveOffer(String sdp);
    void receiveAnswer(String sdp);
    void receiveCandidate(String sdp, String sdpMid, int sdpMLineIndex);
    void close();

}

Connection

ConnectionInterface.java
interface ConnectionCallbacks{

    void onAddedStream(MediaStream mediaStream);

}

public interface ConnectionInterface {

    String targetId();
    void publishOffer();
    void receiveOffer(String sdp);
    void receiveAnswer(String sdp);
    void receiveCandidate(String candidate, String sdpMid, int sdpMLineIndex);
    void close();

}

実装

App(MainActivity.java)

WampTopic監視

Wamp.callback → App の部分。
自分のuserId のトピックを監視する。

  • openしたタイミングで roomIDのみんなにCallme を送る
  • その他はtargetIdから対象のConnection探してそのまま情報を流す

receiveOffer と、 receiveCallme のところで、Connectionを作る。

MainActivity.java
private void setupWamp(){
    // wamp
    String roomId = "abcdef"; // とりあえず固定
    wamp = new Wamp(this, roomId, userId, new WampCallbacks() {
        @Override
        public void onOpen() {
            wamp.publishCallme();
        }

        @Override
        public void onReceiveAnswer(String targetId, String sdp) {

            Connection connection = findConnection(targetId);
            if(connection == null){
                Log.d("onReceiveAnswer", "not found connection");
                return;
            }

            connection.receiveAnswer(sdp);
        }

        @Override
        public void onReceiveOffer(String targetId, String sdp) {
            Connection connection = createConnection(targetId);
            connection.receiveOffer(sdp);
        }

        @Override
        public void onIceCandidate(String targetId, String candidate, String sdpMid, int sdpMLineIndex) {
            Connection connection = createConnection(targetId);
            connection.receiveCandidate(candidate, sdpMid, sdpMLineIndex);
        }

        @Override
        public void onReceiveCallme(String targetId) {
            Connection connection = createConnection(targetId);
            connection.publishOffer();
        }

        @Override
        public void onCloseConnection(String targetId) {

        }
    });
}

相手のストリームを表示

Connection.callback → app の部分。
相手のストリームをもらったらViewを作って表示する

MainActivity.java
Connection connection = new Connection(userId, targetId, wamp, new ConnectionCallbacks() {
    @Override
    public void onAddedStream(MediaStream mediaStream) {

        final VideoTrack remoteVideoTrack = mediaStream.videoTracks.getFirst();

        MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {

                SurfaceViewRenderer remoteRenderer = new SurfaceViewRenderer(MainActivity.this);

                // 〜 略  〜 

                GridLayout remoteViewContainer = (GridLayout) MainActivity.this.findViewById(R.id.remote_view_container);
                remoteViewContainer.addView(remoteRenderer);

            }
        });
    }
});

Connection

webrtcのシグナリング

WebRTC.callback → Connection (→ Wamp) の部分。
Offer/Answer/Candidate がWebRTCから出てくるので、それをWampでpublishして相手に渡す.

Connection.java
this.webRTC = new WebRTC(new WebRTCCallbacks(){

    @Override
    public void onCreateOffer(String sdp) {

        try{
            JSONObject json = new JSONObject();
            json.put("sdp", sdp);
            json.put("type", "offer");
            wamp.publishOffer(targetId, json.toString());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onCreateAnswer(String sdp) {

        try{
            JSONObject json = new JSONObject();
            json.put("sdp", sdp);
            json.put("type", "answer");
            wamp.publishAnswer(targetId, json.toString());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onIceCandidate(String sdp, String sdpMid, int sdpMLineIndex) {

        final JSONObject json = new JSONObject();
        try{
            json.put("type", "candidate");
            json.put("candidate", sdp);
            json.put("sdpMid", sdpMid);
            json.put("sdpMLineIndex", sdpMLineIndex);

            wamp.publishCandidate(targetId, json.toString());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
});

そんなこんなやってるとそのうち

Connection.java
@Override
public void didReceiveRemoteStream(MediaStream mediaStream) {
    callbacks.onAddedStream(mediaStream);
}

相手のストリームが拾えるので拾ったらConnectionに回す。

終わり。

まとめ