Reputation: 1533
In socket.io Android client example project we read that:
IO.socket() returns a socket for http://chat.socket.io with the default options. Notice that the method caches the result, so you can always get a same Socket instance for an url from any Activity or Fragment.
So I decided to test that, because number of opened sockets on my server was not equal to number of clients.
I used following server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendfile('index.html');
});
io.on('connection', function(socket){
console.log('- connect event '+socket.id);
socket.on('disconnect', function () {
console.log('- disconnect event from id '+socket.id);
});
});
http.listen(3000, '0.0.0.0', function(){
console.log('. listening on *:3000');
});
And developed a very simple Android app, that contains two activities, each opens socket.io connection to the same server address and permits to simply switch between activities.
I start the server and launch the app, this is the output I get.
. listening on *:3000
( now I launch the app, opens Activity A )
- connect event 1FIizV3QMdGmnYUQAAAA
( I switch from Activity A to Activity B )
- connect event IzllGFxbpzI5NPNiAAAB
( I switch back from Activity B to Activity A )
- connect event pNt8Yvom5Rih_-01AAAC
- disconnect event from id 1FIizV3QMdGmnYUQAAAA
- disconnect event from id IzllGFxbpzI5NPNiAAAB
This simple test suggests that when onDestroy
event inside the activity I turn off callbacks, socket connection is destroyed, when I restore the activity a new socket connection is opened, but it contradicts so you can always get a same Socket instance for an url from any Activity or Fragment
stated above, because it seems that new instance is being created.
It seems that multiple activity model is very common in Android development ( many people suggest it is inefficient to simply change Fragments over and over again ), how to efficiently share a socket connection between such activities, so that server could have the same socket connection for client no matter how many activities it contains?
Option I considered was creating a BoundService
that would handle all the callbacks and events for socket connection and all Activities could share this service, however I did not find an efficient way of communicating with such service. IPC (inter process communication) in such case could be a huge slow-down, especially if it is based on Intents.
I hope I can get some help on making my app more pro and that it will also be useful for others.
Upvotes: 3
Views: 2074
Reputation: 4258
You can use a Service
to handle the socket and use a Binder
to communicate with the service via arbitrary methods instead of via Intents
. I'm assuming you already know how to work with a started and/or bound Service, if not - read the guide.
You need to override the Service's onBind
callback and return a custom subclass of the Binder
class, which exposes an API for controlling the socket, registering callbacks and the like.
Here's what the code for your Binder
would probably look like:
private final IBinder socketBinder = new SocketBinder();
@Override
public IBinder onBind(Intent intent) {
return socketBinder;
}
public class SocketBinder extends Binder {
// Now you have access to all your Service's public methods
public SocketService getService() {
return SocketService.this;
}
}
Upvotes: 3