4

I understand that on a wifi network there are sudden disconnections which prevent me from sending messages to my server.

But sometimes there's still one last chance before the disconnection, for example if the signal is low or the user is trying to turn off the wifi. On those occasions I would like to send a logout message to my server.

How do I detect disconnections like those?

I tried to retrieve changes of connectivity by registering a broadcast listener:

registerReceiver(this,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
...
public void onReceive(Context context, Intent intent) {
  NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
  if( (info.getState()== State.DISCONNECTING) && (info.getType() == ConnectivityManager.TYPE_WIFI) ) {
    //send logout
  }

But it looks like at that time it's already too late. My logout message doesn't go through.

Is there a better way?

[Update 1] I also tried:

if( (info.getDetailedState()== DetailedState.DISCONNECTING) && connectionTypeOK ) {

[Update 2 - SOLUTION] The solution is, as stated below, using a combination of receiving the RSSI_CHANGED_ACTION and WIFI_STATE_CHANGED_ACTION broadcasts to monitor the signal strength and the WIFI_STATE_DISABLING events respectively. When this happens, I send my logout request. This works exactly as I needed. Thanks!!

Emmanuel
  • 16,791
  • 6
  • 48
  • 74

7 Answers7

4

You could try to implement a variable "heartbeat" function, by using WifiManager to detect changes in signal strength. Here you can find some related code, btw.

Now, once you receive a RSSI_CHANGED notification, according to the corresponding signal strength, you will update the frequency of your app's "heartbeats" to the server: if the signal is strong, you will only need to notify the server infrequently that the app is alive. Once the signal becomes week, however, just like adrenaline kicking in for a real live being, so should your app notify the server more frequently. If the signal's strength recovers, you'll send a specific message to let the server know everything is all right again; if, however, the server does not receive this message in a certain period of time and the "heartbeat" stops - your app ceases notifications for that amount of time - then the server logs it out until receiving from it again.

Community
  • 1
  • 1
luvieere
  • 37,065
  • 18
  • 127
  • 179
  • This is a really good suggestion. Secondly, is there a way to detect wifi being turned off by the user and send my logoff request before it happens? – Emmanuel Apr 25 '11 at 13:56
  • 1
    is it possible to pursue this using the WifiManager's [WIFI_STATE_DISABLING](http://developer.android.com/reference/android/net/wifi/WifiManager.html#WIFI_STATE_DISABLING) Flag? – Dr.J Apr 26 '11 at 10:46
  • I tried WIFI_STATE_DISABLING and I think it's working. So a combination of this and RSS_CHANGED monitoring would do exactly what I need. Thanks a lot!! – Emmanuel Apr 26 '11 at 16:50
1

If you're based on TCP connections, the server should know when a session disconnects unexpectedly - it will get an RST or FIN packet, depending on the router configuration between the client and server. There's no need to do anything from the client's point of view - TCP connections are designed so you can know when they're interrupted.

SirKnigget
  • 3,614
  • 2
  • 28
  • 61
  • This is the "Comet" technique. I can't leave a TCP connection open at all times. – Emmanuel Apr 25 '11 at 13:55
  • This is a bit of a design thing. If you wish to know when your connections are interrupted by network level - use persistent TCP sessions. Are you working with a server that provides only web services? – SirKnigget Apr 26 '11 at 02:16
  • Correct, the back end doesn't have support for this. But if you read luvieere's answer above, this is what I need. – Emmanuel Apr 26 '11 at 14:21
0

Why don't you have the server regularly ping the client, at certain intervals, and just log out if it doesn't get a response? Trying to make this happen through client side will be cumbersome.

omermuhammed
  • 7,365
  • 4
  • 27
  • 40
  • I'm already doing this, but the interval has to be long enough that I don't drain my battery. Logging off would be even better. – Emmanuel Apr 06 '11 at 19:06
0

A better way is not to have sessions at all, if possible.

Why is it a problem if the user doesn't log out?

James L
  • 16,456
  • 10
  • 53
  • 70
  • Well, this won't work because I need to know if the phone is available to receive messages, or if I would be better off directing these messages to someone else. – Emmanuel Apr 06 '11 at 19:08
0

Maybe this is a long shot.. but why don't you use Google push notifications to start an activity if wifi is on. That would tell the server that the phone is "online". If that doesn't happen in X seconds or 1 minute ou whatever, redirect it to somewhere else.

neteinstein
  • 17,529
  • 11
  • 93
  • 123
  • A similar "heartbeat" technique has been suggested and I was already using it. But I really want to add this logout request to make it more real-time. – Emmanuel Apr 25 '11 at 13:56
  • Well then you have to ping each other from X time to X time. That will spend more battery... but to have real-time you have to make some concessions. Either it is real-time... or small batery spending. – neteinstein Apr 26 '11 at 10:14
  • I disagree. There are ways to detect if the wifi signal is low and log out at that point. This is good enough for my needs. Read luvieere's answer. – Emmanuel Apr 26 '11 at 14:20
0

I would implement a handler on the server that handles when the client is not able to receive a message. After each message the phone could send a message back to the server saying it successfully received the message.

  • That has already been suggested. I said that, I'm already doing that. But I would like to send a log out message as well. – Emmanuel Apr 25 '11 at 13:52
0

are you looking for a good way for users to send / receive data after a disconnection?

HTML5 has a local storage (with a good file size too) so if a user is attempting a huge form, you first save it locally and then attempt to send it to server. if failed when the user loads the page again, you can first check if the file has some content, and if so, you can send that data, clear the content and proceed accordingly.

may be this will help you out http://www.html5rocks.com/tutorials/appcache/beginner/

or look at the local storage tutorial: http://www.youtube.com/watch?v=h0uZIljjElo

using this you could save frequent status data and modify it on the fly.

and Android should support HTML5 too.

iamserious
  • 5,385
  • 12
  • 41
  • 60