I am currently developing an android app that gets data from a web server at a user specified interval (5 min, 10 min...). I am using an AlarmManager and a WakeLock. The alarm goes off as expected every 5-10 minutes. The internet connection though doesn't seem to be working during sleep. Most people suggest that I use a WifiLock. Correct me if I am wrong but isn't WifiLock only used to keep WiFi alive? What about 3G-4G mobile data? Does WifiLock keep that connection alive aswell?
Starting with Android 6 due to the new Doze Mode the device enters sleep even with wakelocks, they are ignored.
The way to avoid the device to enter sleep is to start a foreground Service with a non-dismissable notification.
You can't get network access while the device is in Doze mode. If you are hoping to receive notifications or updates from a web service, use Firebase Cloud Messaging, or just defer the network call until the next time it wakes up. You can see more information about Doze restrictions here:
https://developer.android.com/training/monitoring-device-state/doze-standby.html#restrictions
Also, if you are curious about how to check if phone is in Doze mode:
https://developer.android.com/reference/android/os/PowerManager.html#isDeviceIdleMode()
Related
Our company is developing an android application that uses network communication to send GPS signals from devices. The devices are the same and they are all work tools, so we do not have to worry about battery draining, or etc. Currently the activity has a thread, which communicates with the server. The problem is that when the device is locked and it goes to sleep, the network communication breaks.
I've tried to put a partial wake lock to the onPause method to keep the CPU on, and release the wakelock in the onResume method, but it seems not to work. Any idea how to prevent the sleep, or keep flowless communication between the client and the server?
Unfortunately, it is the new behavior, You can read here:
https://developer.android.com/about/versions/nougat/android-7.0-changes.html
See the Doze section.
When a device is on battery power, and the screen has been off for a certain time, the device enters Doze and applies the first subset of restrictions: It shuts off app network access, and defers jobs and syncs. If the device is stationary for a certain time after entering Doze, the system applies the rest of the Doze restrictions to PowerManager.WakeLock, AlarmManager alarms, GPS, and Wi-Fi scans.
It can be solved by using Foreground Service like mentioned above in comments by #egoldx.
It is surely a bad practice to try holding a wakelock, even partial, all the time.
I'm developing an app which connects to a special device via wifi. I need to make status updates in a short interval, resp. keep the status of my special device in the app up to date. FCM is not an option. My idea is to give the user two options: Fast updates using a foreground service or "slow" updates using a periodical update mechanism to save battery.
My question is about the second option. The interval should be around five minutes. Using JobScheduler therefore is not possible. But even using the AlarmManager seems not to be an option because I'm not able to get network access during the doze maintenance windows.
I thought about using a WakefulBroadcastReceiver to receive the Intent by the AlarmManager, require a WakeLock and turn my long running Service into foreground by calling startForeground(). But it seems that the startForeground() method has no effect on the Service as long as the device stays in doze mode.
I read many pages about doze and services but have no clue how to solve my problem... Does anyone got an idea?
you should use GcmTaskService. You can schedule some interval for your operations and it would work fine even in doze mode, check more information by link
You can use setAlarmClock, but it is not recommended for your purposes.
Instead you can use setExactAndAllowWhileIdle with manual re-programming with an interval of 15 minutes.
Best way: GCM.
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'm using a combination of alarm (set with AlarmManager) and background service to periodically synchronize data in my application.
The only problem I have is that when sleep policy terminates Wi-Fi connection the synchronization no longer works.
Is there a way to "wake up" the Wi-Fi connection that has been put to sleep? GMail somehow manages to do that because it notifies me about new e-mail even if the phone entered sleep mode.
[update]You can use a WifiLock to keep WiFi active, while holding the lock.
Using an AlarmManager and a Service says to me your service is running only for a very short time!? I think (though can't say for certain) that you should make your service a forground service (check the blog for a good way to implement this on both 1.x and 2.x+) and leave the AlarmManager out of it.