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.
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.
My application have a realtime module that should ping the server every 60 seconds. Without this, the connection will be dropped and the device will need to reconnect again.
The first attempt was to use a Thread.Sleep to make the pinging thread runs at the desired frequency. The second attempt was to use the ScheduleExecutorService. Both worked very well, but only when the device was charging or with the screen turned on.
After reading a bit, I realized that this behavior happens because the device's processor sleeps and this interferes on the timers. So, the recommendation is to use the AlarmManager...
After start using it, I noticed the my device's screen started to be turned on frequently and I think that this is caused by the alarmmanager that 'wakes the device up'. I searched o bit to see how to use AlarmManager to execute some background actions even if the device is sleeping, without turning the screen on, but nothing was found.
So, there is anyway to use AlarmManager or other approach to accomplish this? Execute a background task even if the device is sleeping, without turning the screen on?
PS1: I know the battery consumption implications due this approach and the request about not turning the screen on is to minimize it's impact.
PS2: The AlarmManager's intent is being consumed by a background service.
Alarm Manager does not turn the screen on. From the docs,
When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running.
I am using it in my code and it does not turn the screen on unless I explicitly set a wake lock policy that turns it on. Take a look at WakeLock
The last 3 are deprecated as of API level 17.
I recommend you to use a PARTIAL_WAKE_LOCK for your task. or you can take a look at WakefulBroadcastReceiver
If you are using onReceive() method, that may be acquiring your wakelock. Remove the WakeLock parameter in onReceive().
I wrote an app recently and, well I'm quite disappointed about how much battery the service consumes. I go to make a call yesterday to find my battery is at 9%; I check the android system statics for the battery and find that my app is responsible for 60% of the battery drainage
My question is, what can one do to reduce the battery usage on an app that runs and then sleeps for 60 seconds? The service is reading from a SQLite database; I could cache the data, but would that really account for that much battery usage? What are some standard ways to reduce battery drainage in a service?
You should look into using AlarmManager to schedule your app or service to be called when necessary. This has a big advantage over your current wake lock method, because even a partial wake lock will keep the CPU running. An AlarmManager alarm can wake the phone even from CPU sleep.
Basically, get rid of your existing wake lock and schedule an AlarmManager alarm—which can repeat once a minute, if that's what you need—to wake up the device, if necessary, and send you a message.
The AlarmManager itself will take out a wake lock while calling an onReceive() method to notify you of the alarm, and relinquish it when onReceive() finishes, letting the phone go back into deep sleep if it wants to.
Note that this means that if you want to do extended work—e.g. firing something off on a background thread—you'll probably want to take your own wake lock out in onReceive() and relinquish it when your work is done, otherwise the phone may go to sleep while you're in the middle of the work.
This is all pretty well-explained in the AlarmManager docs, but the best explanation I've seen is in Mark Murphy's The Busy Coder's Guide to Android Development; he also provides a library for exactly this pattern on Github. Definitely worth a look.
I'm have a widget that is being updated from a service. When the user then turn off the screen, the service stops and won't start to update the widget again when the user wake up the device. So on to my question, is there some way to "restart" the service when the user wake up the device? I know I can keep the service keep going when the screen is locked, but I think it would drain to much battery then... I have google'd alot but haven't found anything...
Thanks in advance!
EDIT: Okey, this is strange! Now somehow it does that automatically, so it's working now! Thanks anyway!
EDIT 2: Or, now I don't really think it's the screen lock that stops the service, cause it just sometimes stops randomly without crashdialog when I use the phone... Anyone know how I should do to fix that?
For a widget it usually doesn't make sense to keep a service running all the time, you usually update the widget periodically.
The easiest way to do this and to be battery efficient is to schedule an intent using AlarmManager and setAlarmInexactRepeating:
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.
The intent should trigger a BroadcastReceiver which in turn should trigger your service to update the widget. Using IntentService is usually a good choice for that.
If you need more control over the intent scheduling, you can also set the alarms yourself in when the service is finished with updating the widget, and supply RTC or ELAPSED_REALTIME as the type of alarms. Both types won't wake up the device if it's sleeping. If the device is not sleeping (but locked) you'll effectively piggy back on other events that woke the device.
If you really need to update as soon as the device is unlocked, the ACTION_USER_PRESENT broadcast might be what you need, but I'd still recommend to implement that as an addition to scheduling a periodic update.
Yes this is Possible!
When the user turn off the screen You Have to handle BroadCast Receiver (http://developer.android.com/reference/android/content/BroadcastReceiver.html)
That handle to Stop service & the service stops and stop to update the widget,
when the user wake up the device you have to Receive Broadcast start to update the widget.
I think it would be The best idea to save more battery.
For More information Please Refer this Link
In my app, I have to make it vibrate in time intervals defined by the user.
Basically it has a chronometer that makes the device vibrate when it has reached the defined time. Currently I do that by reading the chronometer value and comparing it with the desired value, in the onChronometerTick() method
I need this app to work in the background too. I've googled and found some examples about the android Service class.
My doubt is how my Service class will get the chronometer value? I've seen that the Service class can't handle layout components.
How can I do this? Is service the best way to handle this issue?
Thank you!
It sounds like what you want is an alarmmanager. Here's what it says regarding alarm managers:
These allow you to schedule your application to be run at some point
in the future. When an alarm goes off, the Intent that had been
registered for it is broadcast by the system, automatically starting
the target application if it is not already running. Registered alarms
are retained while the device is asleep (and can optionally wake the
device up if they go off during that time), but will be cleared if it
is turned off and rebooted.
So if you're going to want the counter to continue after turning it off, you'll have to find an on-boot option or something. But yes, this is what you need to schedule events if you want them to keep happening after the screen locks.