tsurutanのつぶやき

備忘録としてつぶやきます

Android 簡単にテレビ電話を実装する [Skyway]

f:id:tsurutan:20161004115601p:plain

今回はAndroidでテレビ電話を実装する方法を説明したいと思います。

使用するのはNTT Communicationsさんが提供しているSkywayというライブラリーです。

SkywayはWebRtcを使って、テレビ電話を実現したもので通信処理などの煩わしい部分をこのライブラリーが賄っており、簡単に実装することができます。

Skywayを入れるには?

現在Skywayではライブラリーがmaven上に存在しない為、手動でローカルにとってこないといけません。

github.com

こちらからzipファイルをダウンロードし、解凍したら中にSkyWay.aarというファイルがあるのでそれをandroidプロジェクトのapp直下にあるlibsディレクトリに入れてください。

そして app下のbuild.gradle

compile (name: 'SkyWay', ext: 'aar')

と記入し、プロジェクト下のbuild.gradle

allprojects {
    repositories {
        //何かしらのコード
        flatDir {
            dirs 'libs'
        }
    }
}

と記入すれば完成です。これでAndroid内にSkywayライブラリーをインポートすることができます。

API Keyの取得

Skywayライブラリーを使用するためにはAPI key とドメイン名が必要になるためこちらの公式ページから登録を行ってください。

nttcom.github.io

Skywayの使い方

github.com

こちらのサンプルファイルをベースに説明していきたいと思います。

まず初めにPeerの作成をします。

       PeerOption options = new PeerOption();

        //Enter your API Key.
        options.key = "";
        //Enter your registered Domain.
        options.domain = "";

        _peer = new Peer(context, options);

この時 options.key には先ほど取得したAPI Keyを options.domain にはドメイン名をセットしてください。 PeerOption にはkeyやdomain以外にもhostやport, debugなど様々な設定を与えることができます。

そしてPeerを作成した後にリスナーをセットします。

peer.on(Peer.PeerEventEnum.OPEN, new OnCallback()
        {
            @Override
            public void onCallback(Object object)
            {
                Log.d(TAG, "[On/Open]");

                if (object instanceof String)
                {
                    _id = (String) object;
                    Log.d(TAG, "ID:" + _id);

                    updateUI();
                }
            }
        });

        // !!!: Event/Call
        peer.on(Peer.PeerEventEnum.CALL, new OnCallback()
        {
            @Override
            public void onCallback(Object object)
            {
                Log.d(TAG, "[On/Call]");
                if (!(object instanceof MediaConnection))
                {
                    return;
                }

                _media = (MediaConnection) object;

                _media.answer(_msLocal);

                setMediaCallback(_media);

                _bCalling = true;

                updateUI();
            }
        });

        // !!!: Event/Close
        peer.on(Peer.PeerEventEnum.CLOSE, new OnCallback()
        {
            @Override
            public void onCallback(Object object)
            {
                Log.d(TAG, "[On/Close]");
            }
        });

        // !!!: Event/Disconnected
        peer.on(Peer.PeerEventEnum.DISCONNECTED, new OnCallback()
        {
            @Override
            public void onCallback(Object object)
            {
                Log.d(TAG, "[On/Disconnected]");
            }
        });

        // !!!: Event/Error
        peer.on(Peer.PeerEventEnum.ERROR, new OnCallback()
        {
            @Override
            public void onCallback(Object object)
            {
                PeerError error = (PeerError) object;

                Log.d(TAG, "[On/Error]" + error);

                String strMessage = "" + error;
                String strLabel = getString(android.R.string.ok);

                MessageDialogFragment dialog = new MessageDialogFragment();
                dialog.setPositiveLabel(strLabel);
                dialog.setMessage(strMessage);

                dialog.show(getFragmentManager(), "error");
            }
        });

これでPeerの作成は完了です。

次にカメラで撮影された映像を、自分のデバイスで表示したいと思います。

void startLocalStream(){
        Navigator.initialize(_peer);
        MediaConstraints constraints = new MediaConstraints();
        _msLocal = Navigator.getUserMedia(constraints);

        Canvas canvas = (Canvas) findViewById(R.id.svSecondary);
        canvas.addSrc(_msLocal, 0);
    }

まず初めに 映像を取得するクラス Navigatorに先ほど作成したPeerを渡します。

そして Navigatorのオプション的役割を持つ MeidaConstraints を作成し Navigator.getUserMedia の引数に渡します。

MeidaConstraintsにも様々なオプションがあり、動画のみ、音声のみ、フロントカメラなどの設定をすることができます。

これでstreamが取得できたので、これをCanvasに渡せばローカルのストリーム再生は完成です。

そして最後に呼び出しの部分ですね。

void calling(String strPeerId)
    {
        //////////////////////////////////////////////////////////////////////
        ////////////////// START: Calling SkyWay Peer   //////////////////////
        //////////////////////////////////////////////////////////////////////

        if (null == _peer)
        {
            return;
        }

        if (null != _media)
        {
            _media.close();
            _media = null;
        }

        CallOption option = new CallOption();

        _media = _peer.call(strPeerId, _msLocal, option);

        if (null != _media)
        {
            setMediaCallback(_media);

            _bCalling = true;
        }

        //////////////////////////////////////////////////////////////////////
        /////////////////// END: Calling SkyWay Peer   ///////////////////////
        //////////////////////////////////////////////////////////////////////


        updateUI();
    }

ここの _media = _peer.call(strPeerId, _msLocal, option);でコールをしています。第一引数には呼び出し先のPeer Idを指定しています。

ちなみにPeer IdはPeerを作成するときに指定することができます。デフォルトはランダムでIDは振り当てられます。

第二引数では先ほど作成したローカルのストリームが渡され、第三引数にはCallOptionが渡されます。

はい、これでテレビ電話の実装が完成しました。

いかがでしたでしょうか?

これで皆さんもテレビ電話機能を持つサービスを簡単に作ることができますね!

詳しいドキュメントは公式ページに記載されていますので、ぜひ目を通してみてください。

SkyWay ドキュメント