Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EventSource will not automatically reconnect on Android Firefox

I'm trying to implement an HTML5 app that will work on desktop, android, and iOS. The app's main function is to wirelessly send commands to the server about what scripts to run and to receive regular messages pushed from that server about the status of those scripts.

The server is running nodejs and I decided to use Server Sent Events to do the push notifications. This requires that I use Firefox on Android since the native Android browser doesn't support SSE.

My implementation all works fine: the node server is publishing the events as it should and my client-side HTML5/javascript is picking it up fine on desktop chrome/firefox/safari, on my iPod iOS6, and my Android 2.2 phone.

However, there are 4 common situations that I need to handle:

  • the device loses its wi-fi signal
  • nodejs server crash (hopefully this isn't common!)
  • put browser into the background on iPod/Android while browsing another app, etc.
  • lock screen on iPod/Android while browser is running

Chrome/Safari behave perfectly on both desktop and iPod, as follows: if the server crashes, the site automatically reconnects and gets the pushed messages as soon as the server is up again, and if the browser app goes into the background for whatever reason, it is still getting those messages while in the background, or at the very least automatically reconnects as soon as it comes back into the foreground.

Firefox, however, both on desktop and on Android, is all too eager to close down that EventSource connection permanently. As soon as the browser loses connection to the server, either from server crash, from putting the firefox app into the background or from locking the screen, the EventSource connection is killed and does not ever try to reconnect. Of course, you can just reload the page when you come back to it, but this is annoying, especially in the case where you need to lock the screen because you need to put the phone in your pocket (this app needs to be used in some trekking situations).

Can anyone recommend any solution for this aside from just having to reload the page in Android Firefox all the time? Below is my dummy implementation, just sending random numbers every 5 seconds.

Server at /main/src

src : function(req, res) {
req.socket.setTimeout(Infinity);    

// send headers for event-stream connection
res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
});
res.write('\n');

var messageCount = 0;
var process; 

function printEvent() {
    messageCount++; 
    rand = Math.floor((Math.random()*10000)+1);
    res.write('id: ' + messageCount + '\n');
    res.write("data: " + rand + '\n\n');        

    process = setTimeout(printEvent, 5000);
}
printEvent(); 

res.socket.on('close', function () {
    res.end();
    clearTimeout(process);
});
}

Client

var source = new EventSource('/main/src');

source.onopen = function(e){        
    $("#test").html("Connected to server. Waiting for data..."); 
} 

source.onmessage = function(e){  
    $("#test").html("MSG: " + e.data);
}

source.onerror = function(e){  
    var txt;
    switch(e.target.readyState){  
    case EventSource.CONNECTING:  
        txt = 'Reconnecting...';  
        break;  
    case EventSource.CLOSED:  
        txt = 'Connection failed. Will not retry.';  
        break;  
    }
    $("#test").html("Error: " + txt);
}

Thanks!!

like image 246
kirilisa Avatar asked Oct 07 '22 01:10

kirilisa


1 Answers

i know only one solution, that is already used in many libs: "heartbeat" messages - on the client side you may check, if the "random number" is not received from the server in 10 seconds (5000 seconds + some lag) - the connection is seems to be broken and you should do the reconnection (with native EventSource you may use "close" method, than create new EventSource OR you can try https://github.com/Yaffle/EventSource )

like image 148
4esn0k Avatar answered Oct 10 '22 04:10

4esn0k