When I press the sleep button on the device then turn it back and "update" the uptime shows the time as if the device did not go to sleep.
From Android Reference: SystemClock:
uptimeMillis() is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls), Object.wait(millis), and System.nanoTime().
This clock is guaranteed to be monotonic, and is suitable for interval timing when the interval does not span device sleep. Most methods that accept a timestamp value currently expect the uptimeMillis() clock.
Standard functions like Thread.sleep(millis) and Object.wait(millis) are always available. These functions use the uptimeMillis() clock; if the device enters sleep, the remainder of the time will be postponed until the device wakes up. These synchronous functions may be interrupted with Thread.interrupt(), and you must handle InterruptedException.
--
Seems like your phone is idle or power saving and not technically sleeping...
Assuming the button you are talking about is the "power" or "lock" button, that isn't necessarily putting the device into deep sleep. In fact, looking at the definition of deep sleep (when the uptime counter will stop) I think it would be very rare. The phone will almost certainly keep the CPU running at a low level to monitor for alarm timers and other system scheduled events. If you are wanting to monitor how much time the phone is in "sleep" (screen off, phone locked etc) I suspect you will need to register a broadcast receiver and monitor for those specific events.
take a look at this thread Android - how to receive broadcast intents ACTION_SCREEN_ON/OFF?
also take a look at the power manager
Related
I have two questions.
I want fire a Broadcast receiver using AlarmManager and show a notification in onReceive method. Should I use from WakeLoke for this?
What is different between setAlarmClock() and setExactAndAllowWhileIdle() ?
I use (as you wrote) the onReceive method to start a newWakeLock and it works fine for me.
The difference lies in the behavior in doze mode (Doze Mode: https://developer.android.com/training/monitoring-device-state/doze-standby).
I do not know your exact problem, but I worked very hard to develop an app which contains few timers and every timer should make a notification at the exact time even the screen is locked and the device is in the doze mode. My solution is to fire an Broadcast over an AlarmManager with the setExact(...) method.
Answer your question in reverse order
.2. setExactWhileIdle guarantees that if the system is not sleeping and not in doze, the alarm will go off within 1 minute of the given time. if the system is in doze mode, the alarm will go off within 15 minutes of the given time. In practice, if the system is not in doze mode or low on battery, the alarm will go off on time. On the other hand, setAlarmClock is the closest one can get to a guarentee that the system will deliver the alarm at a specific time; this does come at a relatively large drain on battery. So, if your goal is to implement highly time sensitive notifications such as an alarm clock, then use setAlarmClock. Otherwise try to avoid it.
.1. according to the documentation, upon an alarm being dispatched from setExactAndAllowWhildIdle or setAlarmClock:
the app will also be added to the system's temporary power exemption list for approximately 10 seconds to allow that application to acquire further wake locks in which to complete its work.
My suggestion is that if all you are doing is posting a notification, then a wake lock is not necessary. Otherwise, if you are doing longer running work, use a wake lock
Obligatory Disclaimer: battery drain is a real thing. please don't make an app that drains the battery. do everything in your power to design your app not to disturb the systems power optimization. All exact alarms and especially setAlarmClock disrupt the systems attempts to optimize battery. If its necessary, then its necessary. Otherwise, do not do it.
I'm developing an application which needs to run small chunks of code frequently (once every two seconds, for example). I've tried to make it work using the simple Thread.sleep() (or android.os.SystemClock.sleep() to avoid interrupts, and finally I've tried with Timer and Handler), but the result is that the time that the program sleeps is random (or it simply doesn't run if I use Timer or Handler as the system discards they messages when the screen is off), as the system goes to a deep sleep mode during screen off.
For example the code works right if I have the phone plugged into the charger, or is playing music (that avoids the deep sleep mode), but when the phone isn't doing anything the time can grow from two seconds sleep up to minutes of sleep.
From https://groups.google.com/forum/#!topic/android-developers/Eqwp8Uiy2f0 seems that the only alternative is to use the AlarmManager to force the wake, but that way will probably cause too much battery drain.
Is there any alternative?
If not, is there any way to detect when the system goes into the deep sleep mode?
It is too late but may be useful for somebody else.
Yes, Timers does not work in deep sleep mode.I think there is no other better way than AlarmManager to run something periodically in deep sleep mode.
Also, as your frequency is just 2 seconds I think you may have to go for exact alamrs (setExact() ) as the regular alarm may not serve you better if your requirement is critical in time. And sometimes even setExact might not capture the wake lock I observed. So you have to acquire your own (PARTIAL_..) wake lock and, do stuff and release the lock.
But is it must that you have to run evvery 2 seconds ?
If not continue using Timers which will continue working automatically after the device wake up.
Take a look at Should I use AlarmManager or Handler?
Does anyone know of a way to get the time the device has been in sleep? I am trying to get Awake Time for the device battery and I can get the total time since boot using SystemClock, but they do not have a method for sleepTime. If I could get sleep time, I could do totalTime - sleepTime and get the awakeTime, but not sure on how to get sleep time.
Any suggestions?
Thanks
SystemClock.elapsedRealtime() is "the time since the system was booted, and include deep sleep".
SystemClock.uptimeMillis() is "counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms."
Hence, SystemClock.elapsedRealtime()-SystemClock.uptimeMillis() should be the amount of time in "deep sleep".
I'm writing an app that constantly polls the device's sensors and every so often should write down some statistics to a file. This could be as fast as once a second or as slow once a minute. Should I use Handler's postDelayed()method or just schedule it with the AlarmManager?
This should help you discriminate between Handler and AlarmManager.
[source]
Though it is agreed these mostly work for API 23. It's a new release.
If the app should work in standby then AlarmManager. If not then Handler.
AlarmManager will wake CPU therefore it will drain battery more, while Handler will not work on standby.
Decide your design based on the below key points:
AlarmManager:
The advantage with the AlarmManager is that it works even if the device is in deep sleep mode (CPU is off). When the alarm fires, it hits the BroadcastReceiver and in onReceive, it acquires the wake lock (if you have used WAKEUP types of alarms like RTC_WAKEUP or ELAPSED_TIME_WAKEUP). After finishing the onReceive() it releases the wake lock.
But most of the times it DID NOT WORK for me. So I have acquired my own wake locks in onReceive() and released them at the end to make sure I really get CPU.
The reason why it DID NOT WORK is that when multiple applications simultaneously use a resource (such as wake locks that prevent the system from suspending), the framework spreads CPU consumption across those applications, although not necessarily equally. So, if it is critical, it is always better to acquire wake locks and do the stuff.
Timers and Handlers:
Handler and Timers do not work in deep sleep mode meaning the task/runnable will not run as per the schedule when the device is asleep. They do not count the time in sleep which means that the delay given to execute task will be calculated only during active mode. So, actual delay will be delay-given + time-spent-in-deep-sleep.
I'd say that it depends on the polling interval. I guess it's quite low in your case (around a few secs), so you should go the Handler way, or by using the Timer class.
AlarmManger is a much higher level service and it involves a larger overhead to handle this use case. When an alarm triggers, you need to handle it with BroadcastReceivers. This means that every time you handle one of these alarm, you needs to register listeners for the sensors you're interested in, which is immensely inefficient imho.
I am currently working on customizing an Android system and would like that, a few minutes before going to sleep, a given Activity is run, with the same premises as the sleep function (e.g. if the user performs any action, its timer gets reset).
For instance, let's say that we set its timer to 5 minutes and the device is set to go to sleep after 10 minutes. This means that, as long as there is no user input (or wakelocks acquired etc.), after 5 minutes my Activity is started, and after another 5 minutes the device enters sleep mode (think of it similar to a screensaver).
My initial searches have lead me to the PowerManagerService class, where the ACTION_SCREEN_OFF is broadcast, but the general idea of the code there has so far eluded me.
Any help would be appreciated.
Thank you.
This is not possible, sorry. You have no way of determining system-wide inactivity up until the ACTION_SCREEN_OFF broadcast is sent.
Maybe you can use Wakelock to delay the sleep.
implement a broadcastreceive , filter the ACTION_SCREEN_OFF
when receiving the ACTION_SCREEN_OFF , lock the PARTIAL_WAKE_LOCK
do what you want....
when you finish all the job, release Wakelock. then system go to sleep.