I have a widget/app that performs display [draw...()] operations up to 20 times a second (e.g. animation), depending upon user-selected criteria. When running as a widget, the "full" app is invoked when the widget is touched. (The full app performs similar display operations but has more bells and whistles than the widget.) I want to use the same timing mechanism for both the widget and the "full" app but haven't figured out how to manage this.
Widgets seem to rely on AlarmManager, which does not provide sufficiently accurate timing for my purposes, though it's at least tolerable when running as a widget. Before turning the app into a widget, I used a combination of a Timer and a Handler and this seemed to work OK.
timerHandler = new Handler();
timer = new Timer(timerHandler, drawAction);
Any thoughts on how I might accomplish my goal (assuming it's possible) would be greatly appreciated.
I'm going to agree with CommonsWare here- a widget should not be updating that frequently, widgets should be infrequently updating summaries. Once a second is ok if you're a clock. Anything else should be every few seconds or few minutes.
ANyway, timers and handlers are a pretty old school way of doing animations. Choreographer would be the correct way of getting a regular callback, every 1 60th of a second. Even better, use the Android Animator and Interpolator objects to get regular updates and call setAnimation on your view, avoiding any cheduling of your own.
Related
I am making an Android application using Flash CC and Air for Android. The application will run continuously (part of the time in the background) on multiple devices and will need to keep asking a server about a certain operation and receiving a yes/no answer.
What would be the best approach to do this? If I use a Timer, it seems to have "up to a maximum of 24.86 days" limitation.
Also, what would be a good approach not to waste too much of the battery as the application will continuously run in the background, never turned off.
The limitation on the Timer class is due to the maximum value of an signed, 32-bit integer. Timer stores its current value as an int, in ms since the start. 24.86 days in ms happens to be 2147904000, or close to the max value of a signed, 32-bit integer (2147483647). The difference between the two is likely made up due to rounding in the true max value of the Timer class.
Anyway, your best bet is to reset the timer every single time. So:
var t:Timer = new Timer( delay, 1 );
t.addEventListener( TimerEvent.TIMER_COMPLETE, timerCompleteHandler );
t.start();
function timerCompleteHandler( e:TimerEvent ):void {
// do stuff here
t.reset(); // resets timer to 0
t.start(); // restarts timer
}
In terms of battery usage, that is a tricky question. I've never dealt with an app always running in the background before. I would definitely avoid having it do anything resource intensive. So things like changing any element of the GUI should be off-limits if the app is inactive/running in the background. Really, we need to know more about what you want to do in the background to determine how to help here. From what you have described here, it almost seems like you would be better off setting up push notifications than using a custom call to your server.
In what way that I can have a real-time timer for task scheduling on Android?
Currently I am using Java.util.timer for my real-time application? However, the timer is missing firing when garbage collection is running or other other stuff. The description on java.util.timer says "this class does not offer guarantees about the real-time nature of task scheduling.". Then, which class that I should use on Android then? Or are there any other approach to have a real-time guarantee timer on Android?
Forgot to mention that the timer that I need is at 20 - 40 milliseconds precision level. That means, I need it to fire every 20 - 40 milliseconds.
Handler.postDelayed(Runnable r, long delayMillis);
Does not have a note about whether or not it guarantees it to happen on time. I've used this mechanism before and never noticed any inconsistency with it. However, i've only used it for relatively short intervals (less than a minute) If you are looking for something farther out than that I would suggest you take a look at the AlarmClock application in the Android source. That will probably give you a good approach. That being said if you are looking for extreme precision(down to seconds or farther) I doubt you're going to be able to find anything with guarantees. There are too many things that could be going on that could cause potential misfires.
I have a background service that receives data roughly once per second from an external BT sensor. That data comes in, and gets sent to the UI using a broadcast intent/receiver. The live data is displayed in real time. This all works well right now.
What I need to do now and can't figure out: Have a button on the UI set up so that it starts a count of data coming in from the broadcast receiver (which is coming in roughly every second - but is not consistent enough to set a clock by), and stops after a given duration like 10 seconds. Every time new data comes in, it should be added to the total, and then after the duration of 10 seconds, the UI should be updated with the total, along with some message like "the total was 31".
This sounds easy, but using an async task - which seemed like the way to go - has been giving me trouble since I can't really set the task up to run a loop (afaik) since the looping timing needs to depend on the incoming broadcast receipt.
Any ideas on the best way to accomplish this if not via async task? I imagine the solution might be a simple one, but I'm not seeing it. Thanks for any help!
A Timer and TimerTask would help you with the timing issue and if you wanted to go all out you could implement the timer using ScheduledThreadPoolExecutor.
in numerous places, it is mentioned that app widgets should not get updated often, to minimize power consumption.
But, let's consider that an application is doing something important (such as audio recording) for a short period of time, say 30min.
In this case, is it acceptable to update the widget every second from a service?
How can it be that this would consume so much power?
Please consider that this is different from a widget which would update very often during the whole day.
And in my case, such frequent updates would be meant to allow the user to monitor that the operation is being performed continuously and correctly. It's not for fancy visual effects and such.
I don't see a problem with doing this; if you're keeping the phone awake with a long-running background task (audio recording in this case), then the phone can't sleep anyway. I wouldn't expect updating the widget to have a significant impact on battery use in this case.
Of course, the best thing to do is to run some tests on a real device, and compare battery use with and without widget updates, and make widget update interval a user preference.
The main reason widgets shouldn't update constantly is because of the battery consumption used to get the latest data from a server. Since the device will be on anyway, and the update is local to your data, it shouldn't have an impact that is noticeable.
If you were hitting a server instead of local data every second for that long, you would notice a significant draw on the battery.
I'm writing a sports app that needs to track the elapsed time of quarter/half/period. Elapsed time needs to be accurate to the second. The game clock needs to continue to run even if the user explicitly places the device in sleep mode by pressing the power button.
My first attempt at this involved using Handler.postDelayed() to trigger the clock ticks every 200ms and WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON to ensure that the "clock" wasn't stopped by a screen timeout. But I soon learned that it was possible to circumvent this approach by pressing the power button to manually put the device to sleep. In addition, the postDelayed() approach is experiencing some clock drift, apparently a result of the time spent in the run() method. The actual numbers are still accurate, but instead of being aligned, for example, on 5 second boundaries which are easily understood by users - the timers involved start to drift, resulting in some understandable user confusion.
After a bit of research I found techiques for using services, java timers, AlarmManager, and PartialWakeLock to implement timers. Services by themselves won't solve the problem associated with the device going to sleep. Java timers, like services, don't solve the problem with the device going to sleep. AlarmManager seems like a good approach, but I'm concerned that this isn't an appropriate use of AlarmManager (i.e., very short intervals between alarms). Using PartialWakeLock also looks promising, but by itself it doesn't address the clock-drift problem I'm experiencing.
I'm going to try a combination of AlarmManager and PartialWakeLock. The idea is that AlarmManager will help combat clock-drift and PartialWakeLock to help keep the code simple (fingers-crossed). I'm hoping that this approach will result in a reasonable balance between power conservation, code complexity, and user expectations. Any advice is greatly appreciated.
Thanks,
Rich
I've got a partial solution to my original post above. It doesn't yet address the clock drift associated with the time spent in calculations during the postDelayed() processing, but it is a step forward. In addition, it's deceptively simple, always a good sign.
It turns out I was using SystemClock.uptimeMillis() when I should have been using SystemClock.elapsedRealtime(). The difference between the 2 is subtle, but important.
As you might expect, my solution keeps track of elapsed time by accumulating durations between calls to postDelayed() - i.e., elapsed time = elapsedTime + lastClockInterval. As stated above, the original implementation used uptimeMillis(). Careful reading of the javadoc reveals that uptimeMillis() doesn't include time spent in "deep sleep", e.g., when the user presses the power button. But the elapsedRealtime() method does include time spent in "deep sleep" mode. All that was required to track time across deep sleep cycles was to replace the use of uptimeMillis() with elapsedRealtime(). Success! No need to use AlarmManager, PartialWakeLock, or anything else substantially more complicated. Granted, these methods still have uses, but they are overkill when implementing a simple elapsed-time clock or timer.
The next problem to tackle is with the clock-drift caused by the non-zero execution time associated with postDelayed() processing. I'm hoping that spawning a thread to do the processing will address this issue, allowing postDelayed() to more or less mimic an asynchronous call. Another approach would be to adjust the postDelayed() delay time to take into account the time spent in postDelayed(). I'll post my results.
On an unrelated note, during my investigation I treated myself to a CommonsWare Warescription. While I didn't directly use any ideas from this source for this problem, I do think that it is going to be my Android go-to information source for the foreseeable future. I've got an O'Reilly subscription through my day job, but I've found the CommonsWare books to be as least as good, if not better, source of information about Android development as the O'Reilly resources. And I have found the O'Reilly Safari resources to be pretty good. Interesting...
Cheers,
Rich
I'm sorry this is not quite an answer, but I feel your process is similar to mine, but there was little in regards to code to make it clear how you got around the sleep issue. I don't have drift, but the app does hang when it goes into sleep mode,then kind of resets forward when the display is active, then hangs again when the device sleeps. This is the core of the timer process.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
// do something here to display
processTime(); // process what to be done on a sec by sec basis
try {
timerHandler.postDelayed(this, 1000
} catch (Exception ex){
}
}
};
Is there something here that I can do to allow it to continue when in sleep mode? This use to work on older version of android/devices.