Android persistent socket connection rules
Asked Answered
D

1

40

I have been doing some testing for a custom push notification solution for Android devices using persistent sockets. I would like to share my findings and validate the results.

Simple Description
The applications runs a foreground service and establishes a connection with the server and maintains that connection via aggressive pinging (@ 10 secs interval). If the connection is ever detected as dead, the app keeps trying to reconnect indefinitely. The server sends notifications via duplex channel.

Test 1 :

Pinging is done using a timer at 10 second intervals.
Server sends notification every minute.
Applications acquires wifi and wake locks.
Duration : 8 hours
Battery loss : ~14%

Test 2 :

Pinging is done using AlarmManager at 10 second intervals.
Server sends notification every minute.
Application acquires only a wifilock
Duration : 8 hours
Battery loss : ~7%

Assumptions: An incoming network packet automatically wakes up the CPU, thus no need for a wake lock. Using AlarmManager to ping(instead of timers) means we do not need a wakelock.

Removing that wakelock really seemed to help the battery. Surprisingly, the aggressive pinging on either solution did not affect the battery life as much as I would have expected. (We had many other tests including one where the application just held a wifilock and did nothing which caused around 4% to 5% battery loss over the same period)

Since the application was able to successfully send all the ping requests and receive all the incoming messages, I believe my assumptions are correct. But I would love to get some confirmation from any experts.

One more question: If the application was to instead listen for incoming connections. I would need to hold a wakelock in this case, correct? An incoming connection does not wake up the CPU? We are not going down this route, but just wanted to confirm.

Also, please do not recommend GCM, it has been ruled out by company policy.

Thanks.

Dutybound answered 6/3, 2013 at 17:34 Comment(5)
Why do you let the mobile ping if you've got a socket connection? Why not only let the server send info when there is actually something to say and maybe sometimes a heartbeat to keep it alive.Accretion
In our case the connection can be between a few switches. And we need to determine invalid connections as soon as possible. So for each ping by the mobile client the server has to respond. It protects us against silent disconnects.Dutybound
I'm sure there is a great question in here somewhere but I can't find it in its current form You might consider editing to a more targeted question if you are still looking for answers. JMHO :-)Precondemn
" And we need to determine invalid connections as soon as possible. So for each ping by the mobile client the server has to respond." I thought that underlying transport protocol, I suppose TCP, does that by periodic heartbeats. Is it not the case on Android client? If there are TCP heartbeats, I wonder how much they affect the battery...?Scandium
Great finding..dude....!!Veron
D
16

Since there has been some interest in this question and no confirmations, I will just respond now. It has been a while since the tests were done, and a production level solution has been created and rigorously tested. Removing the wake lock still helped the battery and no other issues were found such as missing ping requests or incoming notifications, so that is the only validation that I received on the said assumptions.

Additional Things to Note:

  • In the OnReceive method of the BroadcastReceiver for the pinging alarm, if you are not directly calling on the socket (spawning a new thread or intent), you will need to hold a wake lock until the ping request is finished. Android holds a wake lock only until OnReceive returns, after that it is possible(but rare) that the CPU may sleep before the ping is finished.

  • Use a High Performance Wifi Lock if the notifications are sensitive.

  • There was one other device specific issue that affected the solution, it is covered here.

Update

Ran into the following issue with Android 5.1 : Android Issue

Update 2

Need to code around Doze mode for Android 6.0 : Doze Mode

Dutybound answered 29/10, 2013 at 17:1 Comment(4)
I know this is an old question, nevertheless: Did you acquire a WakeLock on incoming packets to process these? Or in other words how long is the Device active after being woken from the Network?Derward
Yes, while you will receive the incoming packet without having to hold a wakelock, you should still create a wakelock when you receive incoming data. Otherwise you may not finish processing the data before the device goes to sleep. The how long part, it was different depending on the device. Gotta love that fragmentation.Dutybound
This is quite an old question, but any notes on your update 2 regarding Doze mode? I'm finding that socket connections are not arriving to a 6.0+ Device which I am testing my app in, and I am guessing it is because Doze mode. Despite setting a High performance Wifi Lock it doesn't respond to socket petitions. Is it easy to avoid or ignore Doze mode? Whitelisting?Whiteness
Google is trying to go the route of Apple and really wants you to use their push notification system (Firebase). Luckily, as you said, you can request the user to Whitelist your app from being affected by doze mode (works like permissions). Be aware that unless you have a good reason for the whitelist, Google may reject your app submission to the Play Store. Additionally, when targeting a newer API level, AlarmManager does have some limitations which even the whitelist does not help.Dutybound

© 2022 - 2024 — McMap. All rights reserved.