CodeZine(コードジン)

特集ページ一覧

スマホのネイティブアプリでSocket.IOを利用する

近未来の技術トレンドを先取り! 「Tech-Sketch」出張所 第2回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2013/04/17 14:00

目次

socketio.jarの生成

 https://github.com/Gottox/socket.io-java-clientにアクセスし、リポジトリをZIPファイルとしてダウンロードし、展開します。githubにアカウントがあれば、cloneしても良いでしょう。

 build.xmlがあるディレクトリで `$ ant jar` を実行すれば、jarディレクトリ直下にsocketio.jarが生成されます。socket.io-java-clientが利用するその他のライブラリも、このjarに同梱されています。

 このsocketio.jarを、EclipseのAndroidプロジェクトのlibsディレクトリにコピーしてください。

UIの構築

 レイアウト定義XMLを用いて、iOSの場合と同様のシンプルなUIを構築します。

Socket.IOのクライアントロジックをJavaで記述

 では、クライアント側のロジックを実装しましょう。

 SocketIOからのコールバックは画面更新とは非同期な別スレッドで処理されるため、コールバックメソッドからUIを直接操作できないことに注意してください。

public class MainActivity extends Activity {
    private SocketIO socketIO = null; // SocketIOクラスをインスタンス変数として保持

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ・・・
        // UI部品をインスタンス変数にバインド
        msg = (EditText)findViewById(R.id.msg);
        msgArea = (EditText)findViewById(R.id.msgArea);
        send = (Button)findViewById(R.id.send);
        send.setEnabled(false);
        send.setOnClickListener(onClickSend);
    }
    
    @Override
    protected void onResume() {
        connect(); // 接続処理
    }

    @Override
    protected void onPause() {
        disconnect();
    }

    // サーバからのメッセージ到達など、Socket.IOのコールバック処理を一手にまとめた無名クラス
    // SocketIOオブジェクト生成時にこの無名クラスを与えると、何らかのイベントが発生した際に対応するメソッドが呼び出される
    private IOCallback socketIOCallback = new IOCallback() {
        ・・・
        // Socket.IOサーバへの接続処理(UI表示とは非同期で実行されている)
        @Override
        public void onConnect() {
            Log.d(TAG, "onConnect");
            // UIスレッドでUI部品を操作する
            send.post(new Runnable() {
                @Override
                public void run() {
                    send.setEnabled(true); // 接続に成功した場合、ボタンを押せるようにする
                }
            });
        }

        // イベントを受信した場合のコールバック定義(JavaScriptでの下記処理に相当)
        /* 
          socket.on("broadcast", function(data){
            msgArea.append("<div>" + data + "</div>");
          });
        */
        @Override
        public void on(String eventName, IOAcknowledge ack, Object... data) {
            Log.d(TAG, String.format("on %s, %s", eventName, data[0].toString()));
            if ("broadcast".equals(eventName)) { "broadcast"という名前のメッセージを受け取ったら
                final String received = data[0].toString();
                // UIスレッドでUI部品を操作する
                msgArea.post(new Runnable() {
                    @Override
                    public void run() {
                        msgArea.append(String.format("%s%n", received)); // msgAreaへ受信したメッセージを追加
                    }
                });
            }
        }
    };
    
    // sendボタンが押された際のコールバック(JavaScriptでの下記処理に相当)
    /* 
      send.on("click", function(){
        socket.emit("message", msg.val());
        msg.val("");
      });
    */
    private View.OnClickListener onClickSend = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String message = msg.getText().toString();
            if (message != null && message.length() != 0) {
                socketIO.emit("message", message); // "message"という名前のメッセージをemit
                msg.setText("");
            }
        }
    };
    
    // 接続処理
    private void connect() {
        try {
            // イベントコールバックオブジェクトを指定してSocketIOクラスを生成し、サーバへ接続する
            // (socket.io-java-clientには明示的にプロトコルを指定するAPIが提供されていない)
            socketIO = new SocketIO(Common.getURL(), socketIOCallback);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }
    ・・・
}

 JavaScriptやObjective-Cと違い、Javaにはクロージャ機能がありません。そのため、IOCallbackインターフェースを実装した無名クラスを作り、SocketIOからのコールバックを受け取る関数をその中に書かなければならないのが面倒なところです。

 しかし処理している内容は、JavaScriptやObjective-Cと同様、

  1. Socket.IOオブジェクトを生成してSocket.IOサーバへ接続する
  2. "broadcast"という名前のメッセージを受け取ったらmsgAreaに追記する
  3. ボタンが押されたら"message"という名前のメッセージをemitする

というものです。

 なおGottox/socket.io-java-clientには、Socket.IOのJavaScriptクライアントライブラリやAZSocketIOにはある「接続するプロトコルを限定する」APIが準備されていません。

 もし必要であれば、socket.io-java-clientライブラリのIOConnection#connectTransportメソッドを直接修正すれば対応できます。ソースコードを確認してみてください。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:近未来の技術トレンドを先取り! 「Tech-Sketch」出張所

もっと読む

著者プロフィール

  • 松井 暢之(TIS株式会社)(マツイ ノブユキ)

    TIS株式会社 コーポレート本部 戦略技術センターに所属。 アーキテクチャ設計やデータモデル策定、フレームワーク構築などバックエンド側のアーキテクトとしてプロジェクトに従事していたが、現部門への異動を契機に戦略技術の検証や新規サービスの事業企画に軸足を移す。 近頃はなぜか、インフラ・運用のパター...

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5