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と同様、
- Socket.IOオブジェクトを生成してSocket.IOサーバへ接続する
- "broadcast"という名前のメッセージを受け取ったらmsgAreaに追記する
- ボタンが押されたら"message"という名前のメッセージをemitする
というものです。
なおGottox/socket.io-java-clientには、Socket.IOのJavaScriptクライアントライブラリやAZSocketIOにはある「接続するプロトコルを限定する」APIが準備されていません。
もし必要であれば、socket.io-java-clientライブラリのIOConnection#connectTransportメソッドを直接修正すれば対応できます。ソースコードを確認してみてください。


