Google GCM delay, TCP timeout fix? - android

I have an application which depends on sending instant messages. I use google CSS and XMPP to achieve a persistent connection to the GCM server which works well.
But sometimes there is a delay while receiving the messages (10-15 seconds) on the client side (when on 3G), and I need to find a fix. I was reading that TCP connection timeout can occur while mobile operators often kill connection sockets, so I was thinking if there is a way to have a persistent connection with the GCM server on the client side as well?? Or could pinging the server be helpful?
I would be really grateful for any suggestion.

In order to be a battery efficient service , GCM in order to prevent TCP timeout sends a heartbeat every 18 mins on a 3G mobile device and 28 mins on Wifi . That is the reason why messages are delayed . Well one way to fix it is to send that heartbeat every X minutes . Just put the following code in a timer inside a service .
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Log.e("Trying to save", "GCM or FCM");
getApplicationContext().sendBroadcast(new Intent("com.google.android.intent.action.c"));
getApplicationContext().sendBroadcast(new Intent("com.google.android.intent.action.MCS_HEARTBEAT"));
}
}, 0, 138000{Set this time interval as per your needs;Preferably 5 mins});
CAUTION: Reducing the time interval may result in draining of device battery so
chose that wisely.
This will keep on reviving your connection to GCM servers and you will recieve notifications on time. Good Luck , let me know if it worked

Related

how to change the Android bluetooth connection parameters

I want to change the Android bluetooth connection parameters to be the CONNECTION_PRIORITY_LOW_POWER from the beginning of connection between an Android phone and BLE.
I have tried to add
"mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER)"
after the Gatt connection ("mBluetoothGatt = bluetoothDevice.connectGatt(mContext, false, callback)") or before the paring/bonding.
But it seems that the commection interval when the connection starts remains to be 50ms, which is the default value set by CONNECTION_PRIORITY_BALANCED.
Could you tell me to change the connection interval from the beginning of the connection?
Thanks in advance!
Best regards
Delay your connection priority request (requestConnectionPriority()) until after discovering services.
I believe Android will request a fast connection interval for the service discovery and then switch back to a "standard" interval. It assumes the "start" of your connection is after discovering services, so you must as well.
According to Android docs,
boolean requestConnectionPriority (int connectionPriority)
Request a connection parameter update.
This function will send a connection parameter update request to the remote device.
You shall choose to connect and immediately choose to request the connection priority even after which you can discover services and subscribe to a notification. This way you do not get notifications at undesired connection intervals.

Amazon SQS (Android) handle intermittent network connectivity

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

How can i disconnect in SignalR as my Mobile Data Connections gets off

I had implemented ASP.NET SignalR with Android App. App works great but there is a problem. when i off the data connections, It takes time SignalR to disconnect the connection id created while onConnected() because it try to make connections till the time reach up to disconnection time it try to keep making connections, as a result the period of approx 1.5 min the app become useless. which i don't want. I want if a connection gets break due to loss of connection should be disconnected immediately. Has anyone a solution for that.
You should create your own method to stop the clients connection on such an event. You would probably use something similar to this
connection.hub.stop();
But if you really want the server to not wait you'll adjust the disconnect timeout, but if you do you'll have to adjust the keep-alive timeout accordingly if that was set manually.
DisconnectTimeout
www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events#disconnecttimeout
This setting represents the amount of time to wait after a transport connection is lost before raising the Disconnected event. The default value is 30 seconds. When you set DisconnectTimeout, KeepAlive is automatically set to 1/3 of the DisconnectTimeout value.
// Wait a maximum of 30 seconds after a transport connection is lost
// before raising the Disconnected event to terminate the SignalR connection.
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30);

Receive Android GCM messages so slow?

Google Cloud Messaging (Push message) problem.
I have two smartphones(HTC Sensation XE, Desire HD) and a tablet(Samsung Galaxy Note 10.1 Wifi).
Sometimes I need to wait for almost 15 minutes to receive the GCM push messages. Sometimes I receive the GCM push messages immediately(within 30 secs).
Is it normal? Or just because I'm under Wifi connected?
If it is normal, are there any other services like "long-polling" I can use for retrieving messages from server?
I'm currently using GCM+Polling(AlarmManager) to retrieve messages from remote server.
Any suggestions or better ideas?
Below is my test result:
The left side is server send time, while the right side is client mobile receive time.
All the test results are under Wifi connected environment.
==========================
HD
23:10:18, 23:24:XX
XE
23:11:21, 23:22:44
Note
23:10:20, 23:14:54
==========================
HD
00:08:12, 00:08:27
XE
00:07:55, 00:07:58
Note
00:08:04, 00:13:35
==========================
HD
00:40:21, 00:55:22
XE
00:39:56, 00:40:14
Note
00:40:13, 00:40:59
Thanks!!
GCM uses throttling when there's excessive use, see the following document for more details:
http://developer.android.com/google/gcm/adv.html#throttling
Please read my answer here:
Google Cloud Messaging - messages either received instantly or with long delay
It's basically a tcp timeout problem
You can manually trigger the heartbeat to keep the connection alive by the following code. Some network routers will automatically kill the idle socket connections if it is idle for a particular time period (sometimes 5 minutes). Execute the code in every 5 minute so that the connection will be re-established if it is closed. But, obviously reducing the interval will consume bit more battery (I don't know how much it is relevant here because nowadays the smart phones come up with high mAh battery).
getApplicationContext().sendBroadcast(new Intent("com.google.android.intent.action.GTALK_HEARTBEAT"));
getApplicationContext().sendBroadcast(new Intent("com.google.android.intent.action.MCS_HEARTBEAT"));

Doing something just BEFORE wifi disconnection

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.

Categories

Resources