We are currently creating an application that periodically retrieves data from the server.
When charging or in active state, data can be obtained correctly via Wifi, but when entering DOZE mode and entering sleep state, data cannot be obtained via Wifi and times out.
By the way, I put the application I am creating in a whitelist that does not optimize the battery, and I am going to get data from the server with the startup condition of Worker every 15 minutes.
By adding it to the whitelist, I think that Worker startup is secured, but I guess that Wifi is in sleep state and timed out.
If you look on the internet, you will find examples of task execution using the alarm mechanism. If it is started from the alarm, will the sleep state of Wifi also be canceled? Also, in that case, I would appreciate it if you could give me the URL of the HP where the example code is posted.
Related
I made an application which actually sends User Location to server for every 15 min. This uses Alarm Manager (one shot) which triggers the next one. The alarm manager triggers a foreground service which is responsible for Fetching user location and Uploading to my server.
The flow works awesome when the user is interacting with the device. When screen is turned off (Locked) it works good for some amount of time, Later its not able to send requests and get GPS data. So I used wake lock to turn on screen for 30 seconds so that the device comes out of doze mode.
This approach works fine in Android 8,9 but in Android 10 it still fails. I even used PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF wake lock too but still the HTTP calls and GPS data is being blocked. I implemented a Logger to save every action which stores in files. I see that the service is being invoked, but the GPS Data is not being triggered. One more thing is that I implemented a Timer using Handler and even Timer Task to handle Location timeout so that i can send other data when timeout happens, this works sometimes and fails sometimes.
How can I be able to solve this issue? Is there any workaround.
Note: The reason i used alarm manager is because they actually trigger when device is in doze. Work manager as per my understanding is meant for the jobs that can be postponed. BTW Work Manager was not working in Chinese Roms when app is closed.
I am also facing the same issue and resolved this by disabling the Power saving option in Mobile devices.
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.
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
I want my application to be connected to server though the mobile connection, yet allowing the device to go into sleep mode. I expect it to wake up when IP packates arrives.
How can this be done? How to receive "interrupts" from the Internet without draining battery?
When you are blocked on a read from a tcp stream the device can go into a deep sleep and when tcp traffic comes in it will briefly wakeup the device, as soon as a bit is read in you start a wakelock until you have received the whole transmission then release it.
Here is an example with web sockets, I've ran this app for over 12 hours in the background with no battery impact.
https://github.com/schwiz/android-websocket-example
The client is here, the blocking read is in the start method.
https://github.com/schwiz/android-websockets/blob/master/src/com/codebutler/android_websockets/HybiParser.java
I've been using long living TCP connections on Android without a wake lock for some years now.
My experience is that when data arrives on a TCP connection and the device is in deep sleep, it will be woken up for a short period of time at least. Waking up the device could take up to ~2 minutes sometimes, but it's usually done within a few seconds.
Now that the device is awake, the receiving process has some time too process the data. Now either the process is able to do so before the device is put back into deep sleep, or the device will be put into deep sleep suspending also the process. The important thing here is that the data is not lost, it remains in the memory and the process is able to resume the work processing the data the next time the device leaves deep sleep. Of course, this means that if the sender awaits an answer to his data, it may take some time, until he gets it.
You could take a wake lock as soon as your network library notifies you that a new message was received. But if you done, then make sure to handle the lock properly, i.e. ensure that it is released at some point and in every code path. I personally never experienced the need for a wake lock, the Android device was always long enough awake to process the request. But your millage may vary.
So this is very old but i ended up testing the behaviour #Flow described and just wanted to confirm that there seam to be arbitrary delays sometimes between the arrival of the data and the wakeup of the device.
I tested using a tcpClient implementation and an mqttimplementation. The idea was to see if there is an requirement of instantly getting the wakelock since this delay appeared in my mqtt implementation.
Test steup:
we have 2 services one running the tcpclient and one running the mqttclient in different apps
Both Services run on the same phone with the same permissions in the background.
The Server sends in both cases an "ping" message.
Our client implementation acquires a wakelock as soon as possible and reads the current Date.
for the tcpclient this is instantly
for the mqttclient the wakelock can only be acquired after the arriving data has been propagated through the networking libraries
we send back an response pong message including the read date
this send happens after wakelock release to see if this further delays the response time
the server logs incoming messages with the arrival and the read date
It appears that in both implementations there sometimes is an arbitrary delay to the call to our code. This makes it most likly that there is a delay to the wakeup of the device and not to the acquire of the wakelock.
this delay can be sometimes seen on all devices(tested on huaweip20light, HMD Global#Nokia 7.2, samsung#SM-N960F)
this delay seams more likly to happen on the HMD device higher api and victim of the stricter battery optimisations android established
Google Cloud Messaging might be what you are looking for:
http://developer.android.com/guide/google/gcm/index.html
I have application which for every 10 seconds do some request to server (http client). I read a lot about application life cycle. My application has service with foreground flag and it's work well (application work all time) when android is "active". I don't have phone with real android, so I am testing on emulator, but my friend testing it on smartphone and he notice that when he leave his phone, request are post for 10, 30 minutes, even hour. If he turn on screen, then request time is back to 10 seconds (he have access to server so he see logs). Is this known behavior? Because he installed gmail notifier from google, and this same problem (big delay). Any solution for this? My service have timer task (so request is sent in async task)
Regards
First of all, if you're polling every 10 seconds, that's gonna drain a lot of battery and network bandwidth.
I recommend using a lower frequency or server push.
For the polling issue, how do you implemented the polling ?
Do you use timers ? if so, what options do you pass in ? Or do you use a thread that sleeps for 10 seconds ?
Depending on the version, Android may turn off all processes, or delay network requests to run every 30 minutes to preserver battery power and bandwidth. (Starting up the network components drain a lot of battery than keeping them running. So If your app turns ON network, do a poll, then simply turn it off, Android may schedule it to align with all other requests on the system.)
Can you provide us more info about how you do the polling ?
UPDATE
You might have to schedule a 'WakeLock' so android knows when to wake up for your service. I think, by default, android doesn't wake up for timer requests that are scheduled very frequently and it schedules them as I explained. WakeLocks on the other hand can force android to wake up.
See this question and WakeLock Documentation
Make sure you pass the correct parameters, so you don't turn the screen ON. (Would be really annoying.)
UPDATE
I still recommend using server push for this, which will save battery and bandwidth while keeping the updates real time.
I am running a remote service which has a handler which does an operation every 15 minutes (handler.postDelayed()) which involves making an internet request. Sometimes i notice that it does not happen. Does the internet (mobile data connection get switched off when the mobile sleeps or processor sleeps). What happens during this time ?
I guess internet gets turned off when the screen goes to sleep. What could be the efficient way to make sure that in the required time interval(half an hour) it wakes up (turns the internet on) and does the job in the remote service? This service is supposed to run in the background throughout. Can i do this with an AlarmManager (can it trigger some job to happen in a remote service)?
As stated in a related question's answer, you can give a try to WifiLock if you use only Wi-Fi for this service.
Another reason is maybe your service is destroyed by Android when it sees no use. If it is the case you can try the Foreground service option. Note this does not guarantee the service won't be destroyed but the priority compared to other service will be decreased, thus giving more chance to your service to survive.