Reputation: 97
My need is to have real-time data transfer between two Android devices via 4G. I tried using httpclient POST and GET with memcache, but the latency of mobile carriers is too large (>100ms). I need my data refreshed every 10ms or so. So, I am going the route of a websocket. It took me a lot of searching and digging to come up with this solution, so I'm going to post the barebones code I'm using in case it will help someone. My only issue right now is how to use "nicknames" with my server. I'm using Socket.IO and created my server using Node.JS. Here is the code for my server... I tried to strip everything down to as simple a level as possible, I am just using one variable to be emitted.
var http = require('http');
var url = require('url');
var fs = require('fs');
var server;
server = http.createServer(function(req, res){
}),
send404 = function(res){
res.writeHead(404);
res.write('404');
res.end();
};
server.listen(8001);
// use socket.io
var io = require('socket.io').listen(server);
//turn off debug
io.set('log level', 1);
// define interactions with client
io.sockets.on('connection', function(socket){
//channel 01
socket.on('var', function(data){
socket.broadcast.emit('var',data);
});
});
This is the Java code for the Android device that is sending the data to my server. I just put socket in a thread and am sending the variable "var".
private void beginChannelSync() {
if (mysocket != null)
mysocket.disconnect();
handler = new Handler();
// this sets up the server socket
try {
mysocket = new SocketIO("http://xx.xxx.xxx.x:8001");
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
mysocket.connect(new IOCallback() {
@Override
public void on(String event, IOAcknowledge arg1, Object... arg2) {
}
@Override
public void onConnect() {
}
@Override
public void onDisconnect() {
}
@Override
public void onError(SocketIOException arg0) {
}
@Override
public void onMessage(String arg0, IOAcknowledge arg1) {
}
@Override
public void onMessage(JSONObject arg0, IOAcknowledge arg1) {
}
});
final Runnable r = new Runnable() {
public void run() {
mysocket.emit("var", "some string here");
}
};
syncthread = new Thread() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
sleep(10); // milliseconds
handler.post(r);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
syncthread.start();
}
Below is the code for the Android device that is receiving the code emitted from my Socket.IO server...
// get data stream from DAQ on socket.io server
private class GetData extends AsyncTask<String, Integer, Double> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Double doInBackground(String... params) {
try {
mysocket2 = new SocketIO("http://xx.xxx.xxx.x:8001");
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
mysocket2.connect(new IOCallback() {
@Override
public void on(String event, IOAcknowledge arg1, Object... arg2) {
Object[] arguments = arg2;
jsonmsg = arguments[0].toString();
if (event.equals("var")) {
myvar = jsonmsg;
}
// this makes call to progress so UI can be updated
int values = 1;
publishProgress(values);
}
@Override
public void onConnect() {
}
@Override
public void onDisconnect() {
}
@Override
public void onError(SocketIOException arg0) {
}
@Override
public void onMessage(String arg0, IOAcknowledge arg1) {
}
@Override
public void onMessage(JSONObject arg0, IOAcknowledge arg1) {
}
});
return null;
}
protected void onPostExecute(Double result) {
}
@Override
protected void onProgressUpdate(Integer... values) {
// this is where UI gets updated while getting data stream
tvVar.setText("Var: " + myvar);
super.onProgressUpdate(values);
}
}
When using the code above, everything works great. My question is how to implement the "nickname" such that there can be numerous users with two Android devices. I have searched for code on the internet and found a chat example, but I'm not fully grasping how the nickname works. I visited Socket.IO, but still a little confused. Will someone show me the code I need to add to my server as well as to Java code for the device sending the variable and the device receiving the variable? I know it is only a few lines of code, but it is elusive to me right now. Thanks for any help.
Upvotes: 0
Views: 1639
Reputation: 97
I figured out a way to make the nicknames work for me...may not be the best way, but it works. I'm posting this solution just in case it may help somebody (or at least save some time) in the future. For the server, I added the following code in the 'connection' event
socket.on('set nickname', function (name) {
socket.set('nickname', name, function () {
socket.nickname=name;
socket.emit('ready');
});
});
//code for transferring channel data to client
socket.on('var', function(data){
socket.broadcast.emit('var',{user: socket.nickname, message:data});
});
In the code for the Android activity sending the data, I added this line to the onConnect()
@Override
public void onConnect() {
mysocket.emit("set nickname", "Danica");
}
And lastly, I changed the code in the Android activity receiving the data as follows:
mysocket.connect(new IOCallback() {
@Override
public void on(String event, IOAcknowledge arg1, Object... arg2) {
JSONObject jo = null;
String user = "";
Object[] arguments = arg2;
jsonmsg = arguments[0].toString();
try {
jo = new JSONObject(jsonmsg);
user = jo.getString("user");
} catch (JSONException e) {
e.printStackTrace();
}
if (user.equals("Danica")) {
if (event.equals("var")) {
try {
var = jo.getString("message");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
// this makes call to progress so UI can be updated
int values = 1;
publishProgress(values);
}
Upvotes: 1