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.
Related
I am working on the GPS part of a project and I would like to get something past the community. I have searched around for all the typical GPS "jumping and drifting" and I have worked on improving what I get but last week I got some really weird data that I cannot put my finger on.
The application basically has a foreground service that tracks the location and then uploads that data on a timer. Of course we have all the proper permissions needed and there is also a filter that weeds out data with really bad accuracy and "detects" stops. All was working well until what you can see here happened.
These are some of the data points I got. A "beautiful" pattern drawing. The same happens to another location too but not to this extend. I checked the data to find out why my filter didn't even try to make things better and I found out that it would be unable to. All the points have proper speed, heading, and accuracy and for all intents and purposes I could say that the person actually did the whole thing. The problem is that it didn't happen. The phone, (Samsung J5) might not be the best there is out there, was in a room the whole time. From my understanding of the Fused Location Provider there is no speed reported if there is no GPS involved in the process. And lets assume that where the phone was sitting it could actually get a GPS signal. I can see it jumping around but going for a walk around the neighborhood?
I know and understand that the location in Android (and any other platform) can be a very complicated matter comprised of many different variables that mainly start from the hardware providing these variables, but how can we explain this sudden influx of crazy, even though seemingly proper, data? Can we consider that keeping the location service up and running for a long time actually bogged or "tired" the system? How can the same device that has given OK data to this point suddenly provide this dataset?
To add to the issue. In the data there were also one or two long delays of around 2 minutes (intervals set to 15 and 10 (for fastest) seconds). I am 100% sure that the service did not restart or anything of the kind because I am logging for that.
Any kind of insight would be greatly appreciated and if there is any way/method/algorithm you could recommend looking into to "fix" this kind of behavior would be great. Thank you in advance and sorry for the long question. I needed to provide a proper background.
EDIT: This is not really the answer to my question, why such a behavior suddenly appears, so I am adding it here as a way to try and mitigate the problem, at least a bit. I decided to use the Google's ActivityRecognitionAPI (comes bundled in the location API so no need to have more dependencies) and merged its output with my existing filter to hopefully "fix" the "false" location data.
If someone could still, though, give me a good answer (help me understand) on whether there are factors like long running times, or other hardware (or software) factors (excluding the typical knowledge that GPS chips on phones are bad) that can cause weird and unexpected behaviors like the mentioned one would be rather appreciated.
(We can of course always say - "It is the phones fault" - and be done ;) )
The GPS has errors, so even if you stand still at the same point you will get different readings. There's a couple of things you can do:
Use the accuracy value of the GPS - if the distance between the new reading and the previous one is lower than the accuracy - ignore it.
Use the device's accelerometer in order to determine if it's moving or not.
I am developing an app that allows you to record many clips and stitches them back together before uploading. Whilst developing for Android 5 and up I think this is prevalent problem on all the platforms. Not sure if anyone came up with an usable solution. I seem not to be able to record 1s video as the MediaRecorder takes ~500ms to .start() and on different devices this time changes.
The only method that I found to be more or less accurate is to set up a file observer on media file at the moment when I start() and stop observing when I finish I tend to wait for the first 256bytes to be written before I measure the clip time.
Now then CAN ANYONE tell me whether this is the only thing I can do? Or is there a better method of measuring the delay? Or if you know of an approach I could take to write a recording app that will have immediate start and stop I will greatly appreciate that.
If not maybe point me in the direction of a different approach? Bear in mind I am an absolute beginner so answers like "use MediaCodec API" really not going to help me a lot. I searched for days an appropriate solution can't seem to find anything useful anywhere. Setting thread with a delayedPost is also not an answer.
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.
I have some trouble achieving adequate real-time performance from my application and wondering if I've architect-ed it sub-optimally. The requirement is for the application to play a sound and draw a line on a Canvas at a user specified time interval.
I have a Thread that sleeps for the user-specified time interval, wakes up and uses a Handler and Runnable to do the required drawing and sound playback. When I run the application, the beat is steady sometimes, but other times, you can see the effect of GC and random warning conditions from the AudioFlinger.
Is having a Timer thread post back to the GUI thread via Handler/Runnable the best approach? Is there something I can do to bump up the priority of my app while it is visible so that other apps and Android activity are less likely to interrupt it? Do I need to use the NDK to access real-time features not present in the Java API?
It sounds like what you want to have going is a game loop. There are many tutorials out there on creating game loops with more consistant timing that just sleeping, for example simple java android game loop. You might try searching based on that term, see if it helps.
Also when trying to create real time applications (as in constantly dynamic applications not scientific real time system) you would want to avoid to let the garbage collector run. This takes some time and can be perceived as lag. So don't create objects you need to dispose immediately etc.
Issue:-
I am developing a application which
needs a new acceleration datum every 5
millisecond.
My Approach:-
I have created a remote service
which only reads the acceleration
data from SensorManager.
I had also set the read rate to
"DELAY FASTEST" while initialize the
SensorManager.
Then i use IPC to communicate too my
main application to get these
reading.
Problem:-
If i put a log inside
onSensorChange() event i receive a
new sensor data every 20 ms time. But i need data every 5 ms.
Question ?
Is there any better method to read
the senor data faster.
Is there any way i can poll the
senor data rather that waiting for
the event handler to trigger the
event?
Please help me to find a better solution to read the data in 5 ms time or poll the acceleration data.
As I understand it, the accelerometer is very noisy and not suitable for fast operations. See the GoogleTech talk on sensor fusion at http://www.youtube.com/watch?v=C7JQ7Rpwn2k for a more authorative explanation and what you can do about it. Short explanation: Use the gyro for high speed events and the acceleromenter to correct the drift.
For people referencing this post today, while I think #robinr has a good point and is very true, that is not an answer, however stackoverflow wont let me comment on it directly.
For answers to the first question reference Native Activity. And. Android does not guarantee data rate, it only makes sure that you get the minimum (or maximum if you requesting too much).
The accelerometer is Not noisy, at least not today. Its just way too good at picking up EVERYTHING. So you need to use some filtering if you want a good accelerometer algorithm. If you have excellent filters, accelerometer is actually preferable to all else because it is usually a lower power sensor, has the highest supported frequency, and is most likely to be available when the screen is off(compared to other sensors).
The caveat to a forceful method of using native and extracting the highest frequency is that your device support will be limited. This is why Android doesn't support direct frequency settings.
In response to question 2; your going to have to throttle your sensor events manually by monitoring the timestamp.
Regarding the speed of the Android SensorManager, I would be more inclined to suspect the speed of the Android file I/O that is generating your log. You might try a benchmark of your sensor read code without writing to the log. Something like logging the current time in milliseconds, then doing 1,000,000 sensor reads, then logging the current time again. You might still have to use the C version to get the data, but at least you'll know definitively where the bottleneck lies.
There are a few issues I can see with this. The first is that you are most likely going to bog down the whole rest of the system if you try to force polling of sensor data that fast. If all you are doing is polling sensors that may be ok, but if you want any kind of user interaction, I am not sure that's going to work. Also, why do you need data that fast? If you're interacting with people there is no way there going to notice a lag of even 100ms.
have you resolved your problem?
i have a similar project, to get sample at least every 10 ms (about 100 Hz), here. But, nothing change in samples that i got, even when i set setEventRate = 10 milisec.
So i think there is any hardware limitation since i've read BMA220 datasheet (my sensor hardware) only provides 62,5 Hz for Orientation Sub-mode.