This question got me to think of the way I was writing my battery widget.
ACTION_BATTERY_CHANGED firing like crazy
I'm concerned with the power usage. I saw how frequent ACTION_BATTERY_CHANGED gets fired. Even if you check if the battery level actually changed before you perform the update operation, it still looks a little expensive.
So, which of either listening to ACTION_BATTERY_CHANGED in service or setting alarmservice for like every 5min - 10min to update the widget sound more efficient?
The widget would just be switching ImageView source according to battery level and updating a TextView. Though might consider drawing the text into the image using Bitmap.
You should not care about ACTION_BATTERY_CHANGED events, just use Alarm to check the battery status every 5-10 minutes, that is pretty much enough for your purpose.
On the other hand, do you seriously think someone needs another battery widget in 2013 ?
That depends entirely on if the battery events are raised more frequently than the alarm.
If you're making an app widget make sure you're not updating when not visible.
I made a live wallpaper based on battery level and see no adverse affects of using the battery changed events
Related
Context
I'm working on a screen filter app (like f.lux) for Android. I'm currently working the feature to gradually fade in the filter as the sun sets. The state does not matter when the screen is off, but when the screen is on, it's important that the fade progress be correct (or immediately updated).
Technical requirements
I want to fire a series of intents at semi-regular intervals.
When the screen is off, they can be ignored / discarded, except:
when the screen turns on, the most recent intent must be fired immediately.
I do not want to drain the battery unnecessarily.
Obvious solutions and why they don't work
I could use AlarmManager.setInexactRepeating, which is supposedly the most energy-efficient of the alarms, except:
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.
I think this implies that the first trigger will necessarily happen within the first interval, meaning the device will be woken, causing unnecessary battery drain.
I could use AlarmManager.set to schedule the first alarm. When it goes off, I could update the screen, then schedule the next alarm. This would work, but would wake up older devices (without Doze) on each alarm, instead of waiting until the screen turns on. It's also using AlarmManger as a timer, which the documentation explicitly recommends against:
For timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
Okay, so,
I could set a single alarm to starts up a Handler, which would update the UI periodically. But wait: this relies on postDelayed, which says (emphasis mine):
Time spent in deep sleep will add an additional delay to execution.
I think that means, when the device wakes up from sleep, the next update might not happens for a whole interval. Am I reading this right? Forcing the user to wait a minute or two before the next update is a deal-breaker.
CountDownTimer and ValueAnimator both use this method in their implementations, so if my interpretation of Handler is right, they're both out.
I could use a handler-based method and also receive events when the screen is turned off, at which point I'd cancel the existing animation, then start a new one. This looks to be the best solution, but it seems like there should be a simpler way to do it.
Conclusion
There are a ton of other SO questions on this topic. Everyone and their mother recommends using a Handler, but there's absolutely no information about how it behaves when the device goes to sleep, aside from the quote above. It's really weird that (apparently) nobody else has run into this issue -- am I doing something really unusual, or missing something basic?
Can anybody provide insight about how Handler.postDelayed really behaves when the device goes to sleep, and recommend what I should do in this particular instance?
I want my app to monitor every percent change and be able to execute some code when it changes even when the screen is off.
Yes, I know this is a bad idea and will drain battery unnecessarily. I am giving the user the option to turn this off. Also, this is more of an experiment at this point than a user-friendly feature. So please do not answer that I should not monitor every change.
I also know this is possible because Tasker implements this quite well. You can set a profile to do something on "Battery Changed" and it works when the screen is off. How is Tasker doing this?
From my research I have found that I will probably need to use AlarmManager and a partial wake lock from the PowerManager class. However I don't know how to best use these classes. Should I set an alarm manager to check every minute for a change? Tasker seems to not eat up too much battery when doing this so I would like to keep that in mind.
I have this working when the screen is on just fine. I have a service that registers an ACTION_BATTERY_CHANGED intent filter and a receiver to implement my code that I want to run. However when the screen is off, the code does not run until I "wake" the device by turning on the screen.
How is Tasker doing this?
You would have to ask the developers of Tasker.
Should I set an alarm manager to check every minute for a change?
It would not need to be nearly that frequent. You can only get battery charge levels in integer percentages, at best. Checking every 5-10 minutes is probably more than sufficient. You could also consider:
Letting users control the polling frequency
Implementing a learning algorithm that tries to determine a good polling interval based upon how the device has behaved previously
I have a service that registers an ACTION_BATTERY_CHANGED intent filter and a receiver to implement my code that I want to run.
Yuck. There is no added value for you tying up memory waiting for the battery level to tick over.
You can get the current battery level by calling registerReceiver() with an IntentFilter for ACTION_BATTERY_CHANGED and a null BroadcastReceiver. registerReceiver() will return the last ACTION_BATTERY_CHANGED broadcast that went out. Hence, again, a polling mechanism should be just fine.
I want to write my own clock widget on Android. I am using my own icons to show the time (i.e., updating the ImageView(s) every second). I found a method using AlarmManager to handle the update and implemented it, but I have noticed that the app is using up my battery quickly, which I guess is because of the frequent update.
Is there a more efficient method to do the update?
Appreciate your help.
Thanks & Regards,
Patrick
Battery drain on a frequently updating widget can come from:
*keeping the device awake
--do you really need to wake up the device each time - choose RTC not RTC_WAKEUP
*processing a lot of code each time the widget updates
--do you run a lot of code in onReceive in your broadcast receiver? change your process strategy to do as little processing as possible, because updating every minute is a lot! for example, dont generate data that doesnt need to be updated.
Admittedly I am just kind of hacking here so I would like some knowledge.
I have a service I run in the background connected to another thread that counts down a timer. I was having problems with the count down dying after a while and presumed it was due to garbage collection of the service. I seem to have fixed the issue (and see no real battery use) using startForeground. Now I read about wakelocks, are there any best practices on when to use one or the other?
Thanks!
I have a service I run in the background connected to another thread that counts down a timer.
Please use AlarmManager, so your service only needs to be in memory when it is actually doing work, not just watching the clock tick. One of the biggest user complaints about Android is all these background things that developers create that clog up their phones.
I seem to have fixed the issue (and see no real battery use) using startForeground.
The point behind startForeground() is to indicate that your service is continuously delivering value to the user, such that the user will notice if the service is reclaimed due to hanging around too long or low memory conditions. Sitting and watching the clock tick is not "continuously delivering value to the user". Please use AlarmManager, and you will not need startForeground().
Now I read about wakelocks, are there any best practices on when to use one or the other?
WakeLock keeps the CPU powered on (and possibly other things, like the screen). It has little to do with startForeground(). If you use AlarmManager, depending on the work that you are doing, you may need a WakeLock to ensure the device stays awake while you do your perodic wo
I'm new to Android and Java programming, so I would like to clear up couple of questions I have.
I've written a background service that verifies something every 10 seconds, and, based on some conditions, it may execute something (or may not). This is implemented using a Timer.
My understanding until now is that the timer in the service will run even when the screen is off, so every 10 seconds, even with the screen off, the timer will fire up.
I suppose that this will have an impact on battery life, though I don't know how much or how to measure this.
Now, I don't need the service to do anything while the screen is off, so I'm thinking about registering the Screen OFF and Screen ON broadcast Intents.
On Screen OFF, the code would stop the timer – or would it be better to stop the whole service? – and on Screen ON it would start the timer (or service).
My thought on this direction is that my application will consume less of the battery than it would otherwise
Please tell me if my logic makes sense
If I'm wrong or if there are better ways to achieve this, please let me know.
Thank you!