I want to change user status to show either he is online or not. I want to change user status to false in database when User close application or when he loses connection with server.
As a method is available named as onDisconnect() .I have used that method to update user status by using following code .
HashMap<String,Object> user_online_status=new HashMap<String,Object>();
user_online_status.put("online",true);
DatabaseReference firebaseDatabase=FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
firebaseDatabase.updateChildren(user_online_status);
//then to show user offline
user_online_status.put("online",false);
firebaseDatabase.onDisconnect().updateChildren(user_online_status);
I do that task but as it is on client side and If we want to monitor user connection with server and when connection is terminated node should be updated by Server Instead of Client.How can we change node value from server as User lose connection with server?
There are two ways the user can get disconnected from the Firebase Database.
a clean disconnect, where the client sends a signal to the server before it disconnects.
a dirty (for lack of a better term) disconnect, where the connection gets closed before the client can send a signal.
In the case of a clean disconnect, your onDisconnect handlers will immediately fire and thus your database will immediately be updated.
In the case of a dirty disconnect, Firebase depends on the socket layer to signal when the remote client is gone. This may take anywhere up to a few minutes. But eventually the server will detect/decide that the client is gone, and your onDisconnect handlers will fire.
A small note in your data structure: you that there is a 1:1 relation between a user and a connection. That is unfortunately not the case.
A user may be connected from multiple devices. If they now disconnect from one of those devices, the onDisconnect from that device will set online to false while they may still be connected on another device.
Mobile devices/networks have a habit of going through occasional disconnect/reconnect cycles. This means that you may have multiple connections, even on a single device. In case of a dirty disconnect, the onDisconnect handler may be fired much later, when you've already set online to true for the new connection. In such a case, your lingering onDisconnect handler will set online to false while the user may already be reconnected.
All this is to say that you should not rely on having a 1:1 relation between a user and their connection(s). The samples in the Firebase documentation treat connections as a collection and assume that the user is connected as long as there is any "connect ID" (generated by push()) left for that user. I recommend you do the same to prevent hard to debug race conditions and connection problems.
Related
I have two apps
Client App
and
Server App
in android
What i want
To check in my server app that weather client app has internet connection or not.
What i have done
I had read this post
I have used BroadcastReciever to Listen weather internet is available or not. All is well. When internet connection goes right , i am saving value online to Firebase "true"
But
When internet connection goes off ,
i am using Firebase onDisconnect() method to save ServerValue.TIMESTAMP
It works sometime in two minute but sometime it doesn't update firebase and value remains true.
Note what i want when client app is connected ,on firebase it should save true and when it is not connected it should save false . Though in my server app i will retreive those values to show to client is online or offline
is there any other technique to do such a scenario in android ?
What do you suggest any improvement in my current scenario. ?
Help will highly appreciated.
Thanks
leave this onDisconnect(), write an API that will do nothing but will just ping the server after a fixed time continuously, let's say after each 2 seconds the API will be called(through service), so in case the net is disconnected or the cell phone is even off, since API will not respond to the server, here you will write a code in case app did't ping to the server after 2 seconds(or you can say after 5 seconds), the response(online status) should be FALSE automatically!
so in case the app is again connected to internet, since the service is running so service will update your false into TRUE again
that's too simple!
i think this is your required function!
I'm using Connectivity library to see the internet(Wifi or network data) is active and saving the data in Storage if there is no connectivity(Offline) and synchronize with server when connected to internet. I'm having issues in public places where the internet is consistently unstable(esp. in basements, offices, stores, Coffee shops etc., where there is internet connects in and out). When I check the Connectivity is active but by the time I started synchronizing internet goes offline (Something like this). this leads inconsistent /partial updates to the server. Also, in coffee shops and Airports where wifi gets connected but there will be "Agree Terms and Conditions" page to connect. Not all the browsers will take you to that page directly after joining the Wifi. In that case I see the wifi is active in Mobile but actually it is not activated until I accept the terms and Conditions in IE or some specific browser. Any one else having difficulty in handling these kind of issue from Mobile App?
My App - Hangs on Login screen if I'm trying to login when there is in-stable/in consistent internet.It thinks wifi is there but not.
IF I'm on a screen where I will display list, screen will show blank for infinite time. Adding timeout for server request/response or something will help such scenario.
I know I'm not handling this case in code to show some kind of error message but I need some guidance to detect these conditions suing CN1 API to handle through my app.Please advise.
Code:
public boolean isOffline() {
if (Connectivity.isConnected() && forceOffline) {
relogin();
}
return forceOffline || !Connectivity.isConnected();
}
The problem is that it's impossible to detect online/offline properly as you might be connected to a local wifi/network but it might be a bad connection that won't let you reach the server. As far as the library is concerned you are connected... But in reality you don't have a connection.
First set the timeout values in NetworkManager to lower values to improve the experience although this won't solve a situation where data starts downloading and stops in the middle.
Next you need to handle these cases one by one and provide the user with a way to toggle the offline mode. Unfortunately there is no silver bullet for network reliability. You just need to go through every path and try to detect these things.
I'm trying to figure out how to handle intermittent network connectivity in regards to Amazon SQS on Android. I need to send messages every 10 minutes (or so) and would like any messages that cannot be delivered due to network issues be sent at the earliest time when the network is restored. My hosted service orders messages so getting a few queued messages at once is no issue, but having messages be completely dropped is a problem.
AFAIK, my retry policy is set to retry up to 25 times and then give up. Obviously this is not a great solution, but I didn't see any hooks for network connectivity callbacks or any option to have it retry when the connection is restored if the cause of the error is due to network issues.
The only alternative I can think of (using what I know about this API) is to implement a VERY long-lasting back off strategy and hope the user gets network again with X amount of time, but that seems incorrect.
ClientConfiguration ccfg = new ClientConfiguration();
ccfg.setRetryPolicy(new RetryPolicy(null, null, 25, false));
AmazonSQSClient client = new
AmazonSQSClient(params[0].credentialsProvider, ccfg);
Setting the retry policy is not going to help you in this case.
What you might need to do is:
Cache sqs messages when network is not reachable on mobile.(either file or db).
Implement a network change listener on android and trigger sqs calls when the networks changes from unreachable to reachable.
Take a look at https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html
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!!
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.
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.
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.
A better way is not to have sessions at all, if possible.
Why is it a problem if the user doesn't log out?
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.
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.
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.
I have a simple app that periodically sends HTTP_GET requests to a server. When sending requests over 3G, I noticed that the requests sometimes time out (and the server-side logging shows that it NEVER receives the request either).
After trying out different combinations I found one consistant pattern when this problem occures (it times out after every 5-15 successful requests).
- TelephonyRegistry: notifyDataConnection() state=2isDataConnectivityPossible()true, reason=null
- TelephonyRegistry: broadcastDataConnectionStateChanged() state=CONNECTEDtypes=default supl, interfaceName=rmnet0
- NetworkLocationProvider: onDataConnectionStateChanged 3
According to Google, NetworkLocationProvider is changed to 'DATA_SUSPENDED', which implies "connection is up, but IP traffic is temporarily unavailable". (see TelephonyManager). On the situations where HTTP_GET requests succeeds, the state is changed to '8'. My app doesn't use the location manage and I've shut down every other non-critical app from running!
I want to know:
What is the cause of this issue? Why does the connection status go to DATA_SUSPENDED?
Is it possible to avoid/overcome this problem?
Any help/insight into this is much appreciated! Thanks in advance!
I have the same problem with my app running on an Huawei IDEOS X3 with Android 2.3.5. The app sends data each minute to a server using HttpClient.
Using logcat I can see that the data connection is lost and then reestablished after a short while. Previously my app stopped working since it tried to send data without a connection causing an exception which was not properly handed.
I don't know the reason for the intermittently dropped data connection but I now handle the situation by checking if there is a data connection prior to sending the data. In my case it does not matter if some data is never sent. If it was important to avoid data loss, I could buffer the data and send it once the connection was back.
public Boolean isDataConnection() {
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
return tm.getDataState() == TelephonyManager.DATA_CONNECTED;
}