Androidでsocket.io
socket.io-java-clientを使えば出来るらしいのでちょっと要件検証目的でやってみた。ちなみにsocket.ioサーバーはnode.jsなやつを使う
サーバー側
npm install -g socket.io
-gオプションつける必要あるかどうかはおいといて
var io = require("socket.io").listen(8080);
io.sockets.on("connection", function(socket) {
socket.on("message", function(data) {
// 送った自身以外のクライアントへsend
socket.broadcast.send(data);
});
});
的なsocket.ioサーバーを作って起動しておく
クライアント側 (ブラウザ)
ブラウザで使うsocket.ioのライブラリ(http://socket.io/#how-to-useで書かれてるやつ)は、npmでインストールしたsocket.ioパッケージ内のnode_modules/socket.io-client/dist内に入ってるのでコピペでしておく
<html>
<head>
<script type="text/javascript" src="socket.io.js"></script>
</head>
<body>
<script type="text/javascript">
(function(undefined) {
var socket = io.connect("http://[socket.io.server.ip]:8080");
socket.on("connect", function() {
socket.send("browser(send)");
socket.on("message", function(data) {
console.log(data);
});
});
})();
</script>
</body>
</html>
socket.sendとsocket.emitってのがあるのけどsocket.sendだけ使う。socket.sendだとmessageというイベントキーによりデータをキャッチ出来るので(ry
クライアント側 (Android)
上記にも書いてるsocket.io-java-clientをダウンロードしてくる。ビルドの仕方は書いてるので省略する。socketio.jarをAndroidプロジェクトのlibsディレクトリに突っ込んでおけば良い
でブラウザ側なクライアントから受信したデータをListViewで出すだけっていう単純な事をする
package sample.test.socketio;
import java.net.MalformedURLException;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getName();
Handler mHandler;
ArrayAdapter<string> mAdapter;
SocketThread mThread;
SocketIO mSocket;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
mAdapter = new ArrayAdapter<string>(this, android.R.layout.simple_list_item_1);
((ListView)findViewById(R.id.listView)).setAdapter(mAdapter);
}
@Override
public void onStart() {
super.onStart();
Log.v(TAG, "onStart");
if (mThread == null) {
mThread = new SocketThread();
mThread.start();
}
}
@Override
public void onStop() {
super.onStop();
Log.v(TAG, "onStop");
if (mThread != null) {
mThread.cancel();
mThread = null;
}
}
private class SocketThread extends Thread {
@Override
public void run() {
try {
if (mSocket == null) {
mSocket = new SocketIO("http://[socket.io.server.ip]:8080");
mSocket.connect(new IOCallback() {
@Override
public void onConnect() {
Log.v(TAG, "onConnect");
// connectしたらAndroidからsend
mSocket.send("android");
}
@Override
public void onDisconnect() {
Log.v(TAG, "onDisconnect");
}
@Override
public void onError(SocketIOException e) {
Log.v(TAG, "onError: " + e.getMessage());
}
@Override
public void on(String eventName, IOAcknowledge ack, Object... args) {
Log.v(TAG, "on");
for (Object arg : args) {
if (!(arg instanceof JSONObject))
continue;
JSONObject json = (JSONObject)arg;
onMessage(json, null);
}
}
@Override
public void onMessage(String data, IOAcknowledge ack) {
Log.v(TAG, "onMessage");
update(data);
}
@Override
public void onMessage(JSONObject data, IOAcknowledge ack) {
Log.v(TAG, "onMessage(JSON)");
if (!data.has("msg"))
return;
try {
String msg = (String)data.get("msg");
update(msg);
} catch (JSONException e) {
e.printStackTrace();
}
}
private void update(final String data) {
mHandler.post(new Thread() {
@Override
public void run() {
mAdapter.add(data);
mAdapter.notifyDataSetChanged();
}
});
}
});
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
public void cancel() {
if (mSocket != null) {
mSocket.disconnect();
mSocket = null;
}
}
}
}
んまぁエラー処理とか適当なのでもうちょい厳密的にチェックしなきゃならんのですが。要はIOCallbackで適切なメソッドが呼び出されるってだけなんですが
- emitならonメソッドが作用
- sendならonMessage(以下参考)
っていうようなメソッドが発生する。んまぁonConnectとかそういう系はおいといて、onMessageのメソッドがオーバーロードにより複数存在するのには、socket.ioサーバーにおいて
socket.send("...")
socket.json.send({})
等によって処理されるメソッドが異なるっていう点は注意しなきゃならんかと
んまぁてな感じでやればブラウザクライアントから送ったデータがAndroidにも表示されて、Android側から送ったデータがHTML側にもブロードキャストされてるはず
終わり