Im implementing my own double tap zoom for my OpenGL ES app and am having issues with System.currentTimeMillis(): It seems like when the main thread gets a little busy, it isnt as accurate. 2 taps 200ms apart will show as 600ms apart. What is the most reliable clock to use in Android? I know theres quite a few.
The System.currentTimeMillis() call is quite accurate. The problem is likely that your handler for the tap isn't firing immediately, but because of the load is delayed a few hundred ms.
Related
I've been working on an android game for awhile now. I have the basic game implemented so now I'm going back and trying to optimize. It seems like the battery drain and CPU usage are too high for what I'm doing. I really only have my main thread and then all the drawing and updating is done on a separate thread.
Below is the code for the actual game thread that does updating and all the drawing. All of the actual code has been removed, what's left is what I've been experimenting with to figure out the abnormal CPU usage/battery drain.
So basically if I start the below thread with only an infinite while loop the app uses about 315mAh or about 9% of my phones battery in 30 minutes of use. If I start the thread with no code inside the run method so that it expires after one run through it uses roughly 70mAh or 2% of the phone battery in the same amount of time. The CPU usage also jumps from 2%-3% without the thread running to about 14%-15% when the thread running and just running the infinite loop.
To summarize it seems like running the thread with only an infinite while loop, that does nothing, increases the battery usage by 7% over 30 minutes. I don't see how this is possible and think I must be missing something. I'll keep working to figure this out but there's no more code to take out. If anyone has any suggestions or can provide some insight as to why this is happening I'd greatly appreciate it. Thanks in advance.
class InnerThread extends Thread
{
public InnerThread()
{
super();
}
public void run()
{
while(true){}
}
}
Loops with no delay or pacing are notorious for hogging CPU and battery. Think carefully about whether you really need to be processing continuously, or if once per frame, once per arbitrary time interval, or once each time some external event occurs would be sufficient. Try adding a small arbitrary delay in the loop, and you'll probably see an immediate improvement.
Many games use a main game loop. That's a searchable term. Basically, an endless loop performs some computations, draws a frame, then usually sleeps for some time. (See SystemClock.sleep() vs. Thread.sleep().) Your main loop could pass a frame number and timestamp to the rest of your code. You might compute the positions of moving objects every frame, but you could do more complex things like update the AI of your enemies only at certain intervals of time or frames. If you use a game engine like Unity, the main loop is still there, but you don't write it yourself. You just write the code that it calls every frame.
while(true) is a classical endless loop and probably not required in Java.
it does not even matter on which thread it runs, it's most likely draining the juice.
see Are "while(true)" loops so bad?
I went through and edited my code. Utilizing thread.sleep to limit the overall drawing and updating code to 60 frames per second. Also I made use of the Object.wait() and Object.notify() methods to reduce the unnecessary processing of the thread. I've seen huge improvements, thanks for the help, I really appreciate it. My problem was most definitely that I was wasting battery and CPU power processing nothing.
The thing is, that I have to keep a thread running for a pretty long time (it's really an indefinite time, could be 1 minute or even months), and it needs to update the UI about once every 1 milisecond...
There is the Executor, AsyncTask, Handler and the native Thread class... but which one is better for this case?
The problem with AsyncTask is that it is destroyed (or detached from the Activity?) like one hour or so after the Activity starts running on background, and the user could return to the Activity at any time just to find that it's not working (and even causing memory leaks), and the UI lags when changing to another activity or even pulling down the notification panel.
Natural Threads are even more laggy due to the post() method being called on the TextView every time I need an update to the UI (remember that I need to report progress about once every 1 milisecond)...
tl:dr
I'm developing a long running stopwatch, that can measure from miliseconds to days, weeks or even years. What is the best UI-intensive threading technique for this?
Could you please help me? Thanks!!
--- Edit:
Solved. It had to do something with system resources and the app moving to background. I just had to save the inital time and pauses as a bundle and load them when the app is started again. Thank you everyone!
I'm no Android expert, but I'm guessing that the reason why your AsyncTask gets cancelled is because the OS, being a battery powered OS, is deciding that a long running background task is a bad thing for battery consumption.
Having your program run a background thread for years is going to be a big disappointment for your users who will wonder why their mobiles run out of juice within a couple of hours. I suggest finding another way of doing your time measurement. What's wrong with using the device's real time clock?
I see little point in trying to update a GUI once every millisecond. The OS isn't refreshing the screen at that rate anyway, and no user on earth is going to notice anyway. Plump for once every 40ms at most.
And then there's the matter of accuracy. There's no point trying to measure time with millisecond precision on a device like an Android mobile over periods of hours, never mind days or months. Left alone the clocks and oscillators will be wrong by several seconds a day. The best one will be the real time clock, but even that is going to be pretty poor (they always are). Android is probably doing an NTP updated a couple of times per day, so there will be brief periods in a day when the local clock is close to being accurate (but even then it won't be millisecond accurate).
So even if you do manage to measure time with millisecond precision over months the answers you'll be displaying to the user are going to be wrong by several seconds. You'll be lucky to get within minutes of the actual elapsed time.
If your goal is just to have a stopwatch display rapidly updating when the application is in the foreground, just loop reading the real time clock and calculate/display the time since the stopwatch was started. Don't bother doing anything in the background, just sleep. When your app becomes foreground again resume the loop; the device's real time clock will have been ticking away all the time you're app is asleep, allowing you to calculate and display the time difference. This will be a lot simpler than trying to have a long running background thread, and it will also be more accurate than any other way you might choose (though still not millisecond accurate).
I am trying to build an android application for sphero where I need to stop sphero in certain zones of the room and I am trying to do so with the locatorData using a DeviceMessenger.AsyncDataListener.
I have noticed, however that it is impossible to tell where he is while he is still rolling and stop it when it is in a certain set of coordinates, because the data arrives with great delay. He basically stops much farther and I can see the coordinates increasing with delay on screen. I know the communication is asynchronous and i could somehow be losing some data during communication but I thought that by giving him a window around the coordinates I want him to be I would be able to stop him more or less in that zone, but it doesn't look like it works decently.
For now, the only solution I've come up with is to send a roll command, calculate the amount of time it needs to roll to get to those coordinates based on velocity and send a delayed stop command, but I don't like this solution and I don't think it's going to work correctly in the long run, when I implement all the features I need. Does anyone have any suggestions about the locatorData and how to use it in this case?
I have used the 'locatorData' before and what you are trying to do is very possible. There are a couple ways you can go about accomplishing it.
The great delay you are experiencing is not communication delay, but the fact that the Locator sensor only updates 10 times a second (10Hz). However, this should still be more than enough time to work within your constraints of stopping the ball within a boundary. Another factor is, have you thought about that the ball needs about 1-2 feet to come to a stop? This depends on the speed the ball is traveling when you send a stop rolling command.
One way you cab accomplish your goal is by driving the ball at a slower speed. If you were to drive at 50% power instead of 100% your results should be more accurate. Since, the time delay and stop delay have less impact on the accuracy.
Another way you could accomplish this is by doing a predictive algorithm. Using the 'locatorData', you know where the ball is (x, y), and you know the velocity in which it is traveling (vx, vy) you can predict where it is going to be in the future. Therefore, you can send a stop command in advance when your algorithm determines the ball will be at your destination in 1-2 seconds.
You might want to look into the ConfigureLocator command as well, since this can make the starting point of your ball be (x=0, y=0).
I hope this information helps!
I'm trying to create a music sequencer app for Android devices and would appreciate some advice as to how to achieve rock-solid timing functionality.
If I pass a Runnable to Handler.postDelayed and specify a delay time of x milliseconds, is that Runnable guaranteed to be executed in exactly x ms time?
If I can't achieve steady and accurate timing with Handler, what other options are open to me?
Thank you in advance
After much googling I managed to find the answers here:
http://masterex.github.com/archive/2012/05/28/android-audio-synthesis.html
Handlers, Thread.sleep() and timers are not the way to go it seems.
Thank you DrA for your answer, it was appreciated - sorry for not acknowledging sooner, I've been away for a while.
I don't think "hard realtime" programming is possible. The options seem to be to look for events that signal when something has happened. This can be done by creating your own flag, and polling for the value of that flag in the other thread.
You can use a CountDownTimer to specify a particular length of time must pass in millis.
You can use the System clock and make your own timer, by polling on how much time has passed.
There is also a useful class called FileObserver that allows you to watch a particular file, and hear the events like Opened, and Closed. Using those signals you can know that it is time to move to the next operation.
The worst possible bug is that there is a timing issue that occurs on a specific piece of hardware but doesn't happen on most. The problem if that I don't own all of them, and finding the timing issue is tough. I'm hoping that others will have a better - or more - answers for this issue.
I have a game out on Android, and it runs in a single thread. Performs the work in run() and the draws in onDraw(). Pretty simple.
However, on a Droid it runs much faster than on a G1.
What is a best practice for ensuring that the game runs at the same speed regardless of the device?
This is typically controlled by the combination of using a "game loop" ( http://gamedesign.wikicomplete.info/game-loop ) where the code loops around and draws frames with a timed interval. When using different devices, frames may take longer to draw so this is typically dealt with by either dynamically adjusting the "level of detail" (LOD) and/or using "frame skipping" whereby you don't draw a frame every loop. In fact there's another question that demos a basic algorithm for this:
Allegro 5 game: game loop that runs at constant speed?
-Oisin
Running faster is usually a good thing! The best way for ensuring the game runs correctly on any device is to base your updates on the time passed since last update. This keeps the game feeling consistent when running on a faster device.
Otherwise you could add a sleep call on the faster device - but why not run smoother when you can.