Androidアプリからnode.js+Socket.IOと双方向通信する
AndroidアプリからWebViewなどを介さずにnode.js+Socket.IOと双方向通信するための簡単なサンプルを紹介します。
サーバ側の実装
Androidアプリからnode.js+Socket.IO間で双方向通信するには、socket.io-java-clientというライブラリを使用します。 今回はサーバ側には弊社うえじゅん氏が公開している記事で作ったチャットアプリを使用しますので、まずは以下の記事を参考にチャットアプリを作っちゃってください。
Node + Socket.IO で簡単なチャットアプリの作成
チャットアプリの準備が終わったら、早速Androidアプリ側の準備をしましょう。
Androidアプリの実装
サンプルプロジェクトのダウンロード
今回紹介するAndroidアプリのソースコードをGitHubにあげてあるのでダウンロードしてください。
hakamata/SocketIOSample
サーバ側を起動した状態で、Androidのサンプルアプリを起動してみてください。ブラウザを立ち上げて「http://localhost:3000」にアクセスしメッセージを送信すると、Android側の表示が更新されます。逆にAndroidアプリからメッセージを送信すると、ブラウザ側の表示が更新されます。私はAndroid 4.03のエミュレータで確認しました。
必要なライブラリの設定
ここからは要点をしぼって解説します。
必要なライブラリのダウンロード
Androidアプリからnode.js+Socket.IO間で双方向通信するにはsocket.io-java-clientを使用します。以下のリンクからダウンロードして下さい。
- socket.io-java-client
- Gottox / socket.io-java-client
ダウンロードしたライブラリのインポート
ダウンロードしたライブラリをインポートします。ダウンロードしたライブラリはソースの状態なのでantを使ってjarファイルにアーカイブします。 build.xmlのあるディレクトリに移動してから以下のコマンドを実行すると、jarディレクトリ内にsocketio.jarというjarファイルが作成されます。これをAndroidプロジェクトのlibディレクトリ内に入れればインポートは完了です。
ant jar
socket.io-java-clientの使い方
IOCallbackインターフェイス
IOCallbackインターフェイスでは、以下のメソッドが定義されていますので、適宜実装しておきましょう。
- public void onConnect()
- サーバとの接続が確立されたときに実行されるメソッド。
- public void onDisconnect()
- サーバとの接続が切断されたときに実行されるメソッド。
- public void onMessage(JSONObject json, IOAcknowledge ack)
- JSONを受信したときに実行されるメソッド。
- public void onMessage(String data, IOAcknowledge ack)
- メッセージを受信したときに実行されるメソッド。
- public void on(String event, IOAcknowledge ack, Object... args)
- イベントを受信したときに実行されるメソッド。
- public void onError(SocketIOException socketIOException)
- エラー発生時に実行されるメソッド。
私は以下のように実装しました。
private IOCallback iocallback = new IOCallback() { @Override public void onConnect() { System.out.println("onConnect"); } @Override public void onDisconnect() { System.out.println("onDisconnect"); } @Override public void onMessage(JSONObject json, IOAcknowledge ack) { System.out.println("onMessage"); } @Override public void onMessage(String data, IOAcknowledge ack) { System.out.println("onMessage"); } @Override public void on(String event, IOAcknowledge ack, Object... args) { final JSONObject message = (JSONObject)args[0]; new Thread(new Runnable() { public void run() { handler.post(new Runnable() { public void run() { try { if(message.getString("message") != null) { // メッセージが空でなければ追加 adapter.insert(message.getString("message"), 0); } } catch (JSONException e) { e.printStackTrace(); } } }); } }).start(); } @Override public void onError(SocketIOException socketIOException) { System.out.println("onError"); socketIOException.printStackTrace(); } };
サーバと接続
サーバとの接続するためにはまずSocketIOクラスのインスタンスを生成します。コンストラクタの引数に接続先のURLを設定して下さい。エミュレータを使ってローカルのサーバに接続する場合はlocalhostではなく10.0.2.2にします。
AndroidManifest.xml にandroid.permission.INTERNETのパーミッションを追加するのを忘れないようにして下さい。
接続には、SocketIOクラスの以下のメソッドを使用します。
- void io.socket.SocketIO.connect(IOCallback callback)
- void io.socket.SocketIO.connect(String url, IOCallback callback) throws MalformedURLException
- void io.socket.SocketIO.connect(URLurl, IOCallback callback) throws MalformedURLException
private void connectSocketIO() throws MalformedURLException { // ローカルホストの3000のポートに接続開始 socket = new SocketIO("http://10.0.2.2:3000/"); socket.connect(iocallback); }
イベントの送信
イベントの送信には、emitメソッドを使用します。emitメソッドの第1引数はイベント名、第2引数は送信するデータになります。
public void sendEvent(View view){ // 文字が入力されていなければ何もしない if (editText.getText().toString().length() == 0) { return; } try { // イベント送信 JSONObject json = new JSONObject(); json.put("message", editText.getText().toString()); socket.emit("message:send", json); } catch (JSONException e) { e.printStackTrace(); } // テキストフィールドをリセット editText.setText(""); }
イベントの受信
イベントの受信は、IOCallbackインターフェイスのonメソッドで定義します。onメソッドの中でUIを操作しようとするとCalledFromWrongThreadExceptionがスローされるので注意して下さい。
@Override public void on(String event, IOAcknowledge ack, Object... args) { final JSONObject message = (JSONObject)args[0]; new Thread(new Runnable() { public void run() { handler.post(new Runnable() { public void run() { try { if(message.getString("message") != null) { // メッセージが空でなければ追加 adapter.insert(message.getString("message"), 0); } } catch (JSONException e) { e.printStackTrace(); } } }); } }).start(); }
まとめ
ご覧の通り、socket.io-java-clientを使用すればAndroidアプリからnode.js+Socket.IO間で双方向通信が簡単に実現できます。まだ業務でゴリゴリ使っていないので何とも言えませんが、はまりどころがあれば報告します!