HTML5Experts.jp

SkyWay iOS/Android SDKを使って、WebRTCアプリを開発しよう

連載5回目の今回は、12月にアップグレードされたSkyWayのiOS/Android用SDKのチュートリアルをお届けします。

iOS/Android用SDKを使うことで、SkyWayの特徴である「WebRTCを使ったP2P通信を簡単に実現」することができます。 また、APIもJavaScript版とほぼ同じで、JavaScript版をすでに利用されている方にも実装しやすく、JavaScript/iOS/Android間での通信もサポートしています。

この記事では、そんなiOS/AndroidのSDKの利用方法を、それぞれサンプルアプリのビルド方法や解説を交えながらご紹介していきます。

まずは、iOSのサンプルアプリのビルド方法からご紹介します。Androidのみ開発される方は読み飛ばしてください。

iOSのサンプルアプリのビルド方法

まず、まだSkyWayに登録されていない方はSkyWayのサイトから開発者登録を行ってください。その際の利用可能ドメインですが、ドメインをお持ちでない方は「localhost」等、適当な文字列を指定してください。

次に、iOS SDKをダウンロードします。
iOS SDKのダウンロードページにアクセスして下さい。

ページ下部のDownloadsからダウンロードして下さい。 解凍したフォルダの中に「SkyWay.framework」というものが入っており、これがiOS SDK本体になります。

次はサンプルアプリプログラムのダウンロードを行います。
SkyWay-iOS-Sampleのレポジトリをクローンするかダウンロードを行って下さい。(下図はダウンロードする場合)

次に、サンプルアプリのフォルダにはSDKが含まれていないので、サンプルアプリプロジェクトにSDKを入れます。

先ほどのSkyWay.frameworkを「SkyWay-iOS-Sample > frameworks」内にコピーします。

サンプルアプリを動かすためには、開発者登録をした際のAPIキーとドメインを設定する必要があります。
では、サンプルアプリプロジェクトを開いて設定してみましょう。

SkyWay-iOS-Sample.xcodeprojをXcode(本記事ではVersion 7.1.1)で開き、
SkyWay-iOS-Sample > SkyWay-iOS-Sample内の「DataConnectionViewController.m」を開きます。

//
// MediaConnectionViewController.m
// SkyWay-iOS-Sample
//

import "MediaConnectionViewController.h"

import <AVFoundation/AVFoundation.h>

import <SkyWay/SKWPeer.h>

import "AppDelegate.h"

import "PeersListViewController.h"

// Enter your APIkey and Domain // Please check this page. >> https://skyway.io/ds/ static NSString *const kAPIkey = @"yourAPIKEY"; static NSString *const kDomain = @"yourDomain";

typedef NS_ENUM(NSUInteger, ViewTag) { TAG_ID = 1000, TAG_WEBRTC_ACTION, TAG_REMOTE_VIDEO, TAG_LOCAL_VIDEO, };

コードの上方部分に、上図のような箇所があるので、ここにAPIキーとドメインを設定して保存しましょう。

「MediaConnectionViewController.m」にも同様の箇所があるため、こちらも修正します。

ここまで終わったら、ビルドする端末を接続・選択して、ビルドをします。 以上がiOSのサンプルアプリのビルド方法です。

次はAndroidのサンプルアプリのビルド方法をご紹介します。 iOSのみ開発される方は飛ばしてください。

Androidのサンプルアプリのビルド方法

まずはiOSと同じく、まだSkyWayに登録されていない方はSkyWayのサイトから開発者登録を行ってください。その際の利用可能ドメインですが、ドメインをお持ちでない方は「localhost」等、適当な文字列を指定してください。

次に、Android SDKをダウンロードします。
Android SDKのダウンロードページにアクセスして下さい。

ページ下部のDownloadsからダウンロードして下さい。 解凍したフォルダの中に「SkyWay.aar」というものが入っており、これがAndroid SDK本体になります。

次はサンプルアプリプログラムのダウンロードを行います。
SkyWay-Android-Sampleのレポジトリをクローンするかダウンロードを行って下さい。(下図はダウンロードする場合)

次に、サンプルアプリにはSDKが含まれていないので、サンプルアプリ内にSDKを入れます。

先ほどのSkyWay.aarを「app > libs」内にコピーします。

サンプルアプリを動かすためには、開発者登録をした際のAPIキーとドメインを設定する必要があります。
では、サンプルアプリプロジェクトを開いて設定してみましょう。

サンプルアプリのフォルダををAndroid Studio(本記事ではVersion 1.4)で開き、
app > src > main > java > io.skyway.testpeerjava 内の「DataActivity.java」を開きます。

package io.skyway.testpeerjava;

import ... //省略

public class DataActivity extends Activity { private static final String TAG = DataActivity.class.getSimpleName();

private Peer _peer; private DataConnection _data; private Handler _handler; private String _id; private String[] _listPeerIds; private Boolean _bConnecting; private Runnable _runAddLog; private List<String> _aryLogs; private Bitmap _image;

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

Window wnd = getWindow();
wnd.addFlags(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_chat);
_handler = new Handler(Looper.getMainLooper());

Context context = getApplicationContext();


//////////////////////////////////////////////////////////////////////
//////////////////  START: Initialize Peer ///////////////////////////
//////////////////////////////////////////////////////////////////////


// connect option
PeerOption options = new PeerOption();

// Please check this page. &gt;&gt; https://skyway.io/ds/
//Enter your API Key and registered Domain.
options.key = "";
options.domain = "";

// PeerOption has many options. Please check the document. &gt;&gt; http://nttcom.github.io/skyway/docs/

_peer = new Peer(context, options);
setPeerCallback(_peer);

コードの上方部分に、上図のような箇所があるので、ここにAPIキーとドメインを設定して保存しましょう。

「MediaActivity.java」にも同様の箇所があるため、こちらも修正します。

ここまで終わったらビルドを行い、端末を選択します。 以上がAndroidのサンプルアプリのビルド方法です。

では、コードを参考にしながら、簡単にAPIの使い方を見ていきましょう。

ビデオチャットのコード

iOSとAndroidの二種類のSDKをご紹介をしましたが、この二つのAPIは細かいところを除いては、ほぼ同じです。また、サンプルアプリのコードもほぼ似通ったものとなっています。
そのため、ここではAndroidのビデオチャットのコードを参考にしながら、簡単にAPIの使い方をご紹介します。

また、WebRTC技術についての説明は割愛します。 詳しいWebRTCの仕組みについては、がねこまさしさんが書かれたコチラの記事をお読みください: 壁を越えろ!WebRTCでNAT/Firewallを越えて通信しよう

ではまず、APIの使い方の前に、サンプルアプリの動作を確認します。

このように、

を行う、とてもシンプルなアプリです。

では、この動作に沿ってコードを見ていきましょう。
まずは、SkyWayとのサーバとの接続です。

    //////////////////////////////////////////////////////////////////////
    //////////////////  START: Initialize SkyWay Peer ////////////////////
    //////////////////////////////////////////////////////////////////////

// Please check this page. &gt;&gt; https://skyway.io/ds/
PeerOption options = new PeerOption();

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


// SKWPeer has many options. Please check the document. &gt;&gt; http://nttcom.github.io/skyway/docs/

_peer = new Peer(context, options);
setPeerCallback(_peer);

//////////////////////////////////////////////////////////////////////
////////////////// END: Initialize SkyWay Peer ///////////////////////
//////////////////////////////////////////////////////////////////////

ここではSkyWayのシグナリングサーバとの接続を行っています。

まず、接続を行う時のオプションをPeerOptionクラスで設定します。
このクラスでまず必須なのは、SkyWayを利用するためには必須となる「APIキー」や「ドメイン」の設定です。
そのほかにも、SkyWayが提供するTURNサーバの利用を選択する「turn」プロパティや、自前のSTUN/TURNサーバを設定する「config」プロパティ等の設定が可能です。もっと詳しく知りたい方はドキュメントをご参照ください。

次に16行目では、このオプションを使ってシグナリングサーバと接続を行っています。
このPeerクラスはシグナリングサーバとの接続を管理しており、「connect/call」メソッドでのP2Pのデータ/メディア通信の開始や、「listAllPeers」メソッドでのAPIキー毎のアクティブなPeerIDを取得、などができます。
実際にサンプルアプリでは、「Calling」というボタンを押すとlistAllPeersメソッドを呼び出し、PeerID一覧の取得を行っています。

続いて17行目では、このPeerオプジェクトのコールバックを設定しています。
コールバックの説明の前に、ローカルの映像取得部分を見てみます。

    //////////////////////////////////////////////////////////////////////
    ////////////////// START: Get Local Stream   /////////////////////////
    //////////////////////////////////////////////////////////////////////
    Navigator.initialize(_peer);
    MediaConstraints constraints = new MediaConstraints();
    MediaStream _msLocal = Navigator.getUserMedia(constraints);

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

//////////////////////////////////////////////////////////////////////
//////////////////// END: Get Local Stream   /////////////////////////
//////////////////////////////////////////////////////////////////////

ここでは、ローカルの映像取得を行って、得た映像ストリームをViewに表示しています。
NavigatorオブジェクトのgetUserMediaメソッドを呼び出すことで、MediaSteamオブジェクトの映像ストリームを得ることができます。その際に、MediaConstraintsというオプションを指定することで、映像/音声の利用可否の指定、インカメラ/アウトカメラの指定、などを行うことができます。

また、CanvasクラスはGLSurfaceViewを継承しており、得た映像ストリームはCanvasオブジェクトのaddSrcメソッドで表示することができます(iOSのSKWVideoオブジェクトはUIViewを継承しています)。

では、話を戻してPeerオブジェクトのコールバックを見てみましょう。

    //////////////////////////////////////////////////////////////////////////////////
    ///////////////////// START: Set SkyWay peer callback   //////////////////////////
    //////////////////////////////////////////////////////////////////////////////////
    // 簡単のため、適宜、省略しています

// !!!: Event/Open
peer.on(Peer.PeerEventEnum.OPEN, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    // シグナリングサーバと接続された
    _id = (String) object;

    updateUI();
  }
});

// !!!: Event/Call
peer.on(Peer.PeerEventEnum.CALL, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    // 相手から通話がかかってきた
    _media = (MediaConnection) object;

    _media.answer(_msLocal);

    setMediaCallback(_media);

    updateUI();
  }
});

// !!!: Event/Close
peer.on(Peer.PeerEventEnum.CLOSE, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    // シグナリングサーバとの接続ステータスがdestroyedとなった
  }
});

// !!!: Event/Disconnected
peer.on(Peer.PeerEventEnum.DISCONNECTED, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    // シグナリングサーバとの接続ステータスがdisconnectedとなった
  }
});

// !!!: Event/Error
peer.on(Peer.PeerEventEnum.ERROR, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    // 何かしらのエラーが発生した
  }
});

//////////////////////////////////////////////////////////////////////////////////
/////////////////////// END: Set SkyWay peer callback   //////////////////////////
//////////////////////////////////////////////////////////////////////////////////

ここでは、シグナリングサーバから送られたイベントに対し、処理を行っています。

7行目は、シグナリングサーバとの接続が確立した際の「OPEN」イベントでの処理です。
ここでのObjectは、シグナリングサーバから自分に割り当てられたPeerIDが格納されており、サンプルアプリでは、そのPeerIDを表示しています。PeerIDはnew Peer時にIDを指定することもできますし、指定せずにランダムなIDを取得することもできます。

20行目では、他のPeerから通話がかかってきた際の「CALL」イベントでの処理です。
ここでのObjectはMediaConnectionクラスであり、answerメソッドを呼ぶことで、先ほど作成した自分の映像ストリームを返しています。引数を与えないことで、映像ストリームを返さないことも可能です。
そのあと、30行目でMediaConnectionのコールバックを設定しています。

このように、相手からの通話を受ける際は、Peerオブジェクトのコールバック内で「CALL」イベントで処理を行います。
自分から通話する場合は、下記のようにPeerオブジェクトのcallメソッドを呼びます。

    //////////////////////////////////////////////////////////////////////
    ////////////////// START: Calling SkyWay Peer   //////////////////////
    //////////////////////////////////////////////////////////////////////
    // 簡単のため、適宜、省略しています

CallOption option = new CallOption();

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

setMediaCallback(_media);

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

この部分は、listAllPeersメソッドで得られたPeerIdの一覧から、通話したいPeerIDをタップした時に呼ばれます。

このように、呼び出し時のオプションを設定し(このコードでは何も設定していませんが)、通話をしたいPeerIDと自分の映像ストリームを指定してcallメソッドを実行します。返り値は通話がかかってきた際と同様、MediaConnectionクラスで、MediaConnectionのコールバックを設定しています。

では、MediaConnectionのコールバックを見てみましょう。

    //////////////////////////////////////////////////////////////////////////////////
    //////////////  START: Set SkyWay peer Media connection callback   ///////////////
    //////////////////////////////////////////////////////////////////////////////////
    // 簡単のため、適宜、省略しています

// !!!: MediaEvent/Stream
media.on(MediaConnection.MediaEventEnum.STREAM, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    _msRemote = (MediaStream) object;

    Canvas canvas = (Canvas) findViewById(R.id.svPrimary);
    canvas.addSrc(_msRemote, 0);
  }
});

// !!!: MediaEvent/Close
media.on(MediaConnection.MediaEventEnum.CLOSE, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    Canvas canvas = (Canvas) findViewById(R.id.svPrimary);
    canvas.removeSrc(_msRemote, 0);

    _msRemote = null;
    _media = null;

    updateUI();
  }
});

// !!!: MediaEvent/Error
media.on(MediaConnection.MediaEventEnum.ERROR, new OnCallback()
{
  @Override
  public void onCallback(Object object)
  {
    // 何かしらのエラーが発生した
  }
});

//////////////////////////////////////////////////////////////////////////////////
///////////////  END: Set SkyWay peer Media connection callback   ////////////////
//////////////////////////////////////////////////////////////////////////////////

7行目は、通話相手の映像ストリームを取得した際の「STREAM」イベントでの処理です。ここでのObjectは、MediaStreamオブジェクトです。自分の映像ストリームと同じくCanvasオブジェクトを利用して表示しています。

20行目では、通話相手との通話が切断された際の「CLOSE」イベントでの処理です。

ここまでが、簡単なSkyWayを使ったWebRTCの処理になります。

最後に、最近のアップデートで追加されたメソッドについてご紹介します。

    Button switchCameraAction = (Button)findViewById(R.id.switchCameraAction);
    switchCameraAction.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View v)
      {
        Boolean result = _msLocal.switchCamera();
        if(true == result)
        {
          //Success
        }else
        {
          //Failed
        }
      }
    });

MediaStreamオブジェクトがローカルの映像ストリームの場合、switchCameraメソッドを呼び出すことができます。
これにより、今まではできなかった、「getUserMedia後のインカメラ/アウトカメラ切り替え」が可能になります。

以上が、サンプルアプリの簡単なコード解説になります。今回はビデオチャットだけの紹介でしたが、ほぼ同じようなAPIでテキストや画像が送れるデータチャットも可能です。

おわりに

今回は、SkyWayのiOS/Android用SDKのチュートリアルをお届けしました。

JavaScript版と同じように、手軽にWebRTCが利用可能です。 是非ご自身のアプリケーションに組み込んでみてください!