I am trying to create a kind of a metronome for Android. It shall play some audible beeps at certain intervals to give people a rhythm. Hence, timing is quite critical. Essentially it shall do the following
(start)
Play beep type 1 (about 0.1s long)
Wait for x milliseconds (between 500 and 1000)
Play beep type 2 (about 0.1s long)
Wait for y milliseconds (between 500 and 1000)
Play beep type 3 (about 0.1s long)
Wait for y milliseconds (between 500 and 1000)
Go back to start
The UI activity will have some buttons to adjust the wait intervals.
From reading all the various blogs, tutorials and discussions it seems that I should be using a postdelayed() Runnable and set the delay to my desired wait time x or y. After that I should start playing the sound. This should allow me to not take the length of the wav sound file into account.
Am I roughly on the right track? I realise that the timing will not be perfect as there are other services running which might delay the execution of my timers. In order to improve that I'd be happy to use the phone in flight mode or turn of some other services as I don't need anything else when using this app.
Are there any full examples for such code out there? I am a beginner when it comes to Android. My eyperience is more with straight C embedded systems. Putting all the classes and their functions together is quite daunting.
Any help appreciated,
Michael
An idea that just came to my mind regarding the waiting between the beeps would be to launch a separate Java thread where you enter in an infinite loop and call Thread.sleep(interval) like
public MyLooper extends Runnable{
private boolean shouldRun = true;
private int interval = 1; //ms
#Override
public void run(){
while(shouldRun){
//play the beep
Thread.sleep(interval);
}
}
public void stop(){
this.shouldRun = false;
}
public void setInterval(int interval){
this.interval = interval;
}
}
When you launch your activity (depending on your needs) usually in the onResume event, you'd create the Java thread. Inside the button clicks you could then adjust the interval by calling the setInterval(...) method.
Could be a possible solution...
This is what you need:
Updating the UI from a Timer
EDIT: That tutorial is specifically targeting a UI-update scenario, but it gives a simple description of what you really want: a TimerTask
class UpdateTimeTask extends TimerTask {
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timeLabel.setText(String.format("%d:%02d", minutes, seconds));
}
}
and
if(startTime == 0L) {
startTime = evt.getWhen();
timer = new Timer();
timer.schedule(new UpdateTimeTask(), 100, 200);
}
Related
So, I borrowed a timer approach from this excellent post:
Android timer? How-to?
which was very well-written and well-upchecked. However, I find that it fires approximately every 106-114msec, not the desired 100msec. Does this make sense, or does it seem slow? If I wanted to make this closer to an exact 100msec (I am using it in some places to measure durations), what change should I make?
My code is below
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
TickTimer_Elapsed();
timerHandler.postDelayed(this, 100);
}
};
void TickTimer_Start() { timerHandler.postDelayed(timerRunnable, ); }
void TickTimer_Stop() { timerHandler.removeCallbacks(timerRunnable); }
void TickTimer_Elapsed()
{
m_FSM.Tick_10Hz(); // actually a bit slower than 10Hz
}
Timer is overloaded term in English, meaning either a device that measures time (e.g. a stopwatch), or a device that triggers after a time (e.g. egg timer).
In Android, the timer is for the latter only, and it does not promise absolute accuracy.
"I am using it in some places to measure durations"
In real life, to tell how much time has passed, you would not to watch a clock and count the seconds ticking by! You'd get nothing else done in that time. An efficient way would be to look at the clock just twice and subtract the two times. The same is true with computers:
e.g:
long startTimeMs = System.currentTimeMillis();
Later:
long durationMs = System.currentTimeMillis() - startTimeMs;
I'm new on android application and i'm creating an app that shows a video using a VideoView, I use a CountDownTimer to search each 15 seconds for video updates and play another video. My app works very well during 2 or 3 hours but after this my app just stop, the application doesn't close but is stopped and I must close and open again. What should I do? Thanks.
It literally stops on the screen, it stops the timer and video view.
Here is the code that i'm using to count time to call functions to show video and time.
new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
time++;
downloadTime++;
if(downloadTime == 2){ // Should be executed each 2 seconds
DoDownloads();
downloadTime = 0; //
}
showPlayer();
showTime();
}
public void onFinish() {
this.start();
}
}.start();
I can't show any log because this happens after some hours and can be 2 hours or 10 hours, and i'm testing on tablet.
We would need the code of the rest of your functions, like DoDownloads(); showPlayer(); showTime();
anyways, i wouldnt restart the countdown that way. Id try with a handler and postdelayed(Runnable), like:
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
time++;
downloadTime++;
if(downloadTime == 2){ // Should be executed each 2 seconds
DoDownloads();
downloadTime = 0; //
}
showPlayer();
showTime();
handler.postDelayed(this, tiempo);
}
};
handler.postDelayed(runnable, tiempo);
And also, you should debug the app and copy/past the log cast in the moment it fails, and give us some information about in what point the execution wsa
I'm working on a presentation app, which displays different images. There I wanted to to let the presentation slide through my List of images, video and pdf files, after a short amount of time.
I start my different views through intents, startActivityForResult(intent, RESULT_OK);
Starting videos and closing videos was not an issue. I used onPreparedListener and setOnCompletionListener and everything worked like a charm.
With pictures however, this was completely diffrent.
I created a new Thread in my ImageView and did put that thread to sleep(), after that I called the setresult() method and finish(). But instead of waiting, the picture wasn't shown at all and the presentation was stuck there, without setting the result and finishing the activity.
So I started searching for some explanation of time in android and found this explanation:
Explanation
I read through it and tried to get a good grasp on whats explained there. But the more I thought about it, the more I got insecure, which is the best way to implement the waiting behavior for my intended purpose.
So instead of some code, I am much more interested in, what you would advise me to use and why with a, if possible, detailed explanation.
elapsedRealtime()?
uptimeMillis()?
System.currentTimeMillis()?
From android docs:
• System.currentTimeMillis() is the standard "wall" clock (time and date) expressing milliseconds since the epoch. The wall clock can be set by the user or the phone network (see setCurrentTimeMillis(long)), so the time may jump backwards or forwards unpredictably. This clock should only be used when correspondence with real-world dates and times is important, such as in a calendar or alarm clock application. Interval or elapsed time measurements should use a different clock. If you are using System.currentTimeMillis(), consider listening to the ACTION_TIME_TICK, ACTION_TIME_CHANGED and ACTION_TIMEZONE_CHANGED Intent broadcasts to find out when the time changes.
• uptimeMillis() is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls), Object.wait(millis), and System.nanoTime(). This clock is guaranteed to be monotonic, and is suitable for interval timing when the interval does not span device sleep. Most methods that accept a timestamp value currently expect the uptimeMillis() clock.
• elapsedRealtime() and elapsedRealtimeNanos() return the time since the system was booted, and include deep sleep. This clock is guaranteed to be monotonic, and continues to tick even when the CPU is in power saving modes, so is the recommend basis for general purpose interval timing.
If the time interval, you're going to measure, is relatively short, you can use pretty much any method which gives you correct time. I prefer currentTimeMillis(). In case the time interval is really long, the recommended method is to use elapsedRealtime().
Also, if you only want to do something with a delay, simply use: http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable, long) . It's simple and works great.
Simplest way to achieve that is CountDownTimer
private final class CountDownTimerImpl extends CountDownTimer {
//5 sec.
private static final long TIME_INTERVAL = 5000;
private final ImageView imageView;
private final List<Drawable> images;
public CountDownTimerImpl(ImageView imageView, List<Drawable> images) {
super(TIME_INTERVAL, TIME_INTERVAL);
this.imageView = imageView;
this.images = images;
//set first image from images array to imageView
imageView.setImageDrawable(images.get(0));
}
//this method is executed after TIME_INTERVAL (5 sec.)
public void onFinish() {
//remove drawable from imageView
imageView.setImageDrawable(null);
//remove this drawable from array
images.remove(0);
//if array is not empty start another count down
if (!images.isEmpty()) {
new CountDownTimerImpl(imageView, images).start();
}
}
public void onTick(long millisUntilFinished) {
//nothing to do here
}
}
You should start this CountDownTimer by:
new CountDownTimerImpl(imageView, images).start();
where images is of course an drawables array of your presentation images.
I have no time to test this solution but it should work - if not please leave a comment and I will update it later.
You can use TimerTask
int counter=0;
final Handler handler = new Handler();
Timer ourtimer = new Timer();
TimerTask timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
counter++;
//you can do stuffs here say like if (counter==15) { do something}
}
});
}};
ourtimer.schedule(timerTask, 0, 1000);
You can do this in a different way writing a callback module
Create a activity call it BaseActivity and let all you activities to extend it
Now declare a method call is void callback(){} keep the body empty
now in onCreate create a timer as above and call the callback function your code will look like
onCreate(){
final Handler handler = new Handler();
Timer callTimer = new Timer();
TimerTask timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
callback();
}
});
}};
callTimer.schedule(timerTask, 0, 1000);
}
Now in you activity override the callback method which will be called after the time you specified in timer,
Ex
Class a extends BaseActivity(){
#Override
onCreate(){
// playVideo
}
#Override
void onCallBack(){
//navigate to another activity
}
}
i have an activity in which i want to track the time elapsed between two actions(for ex startAction and endAction).I've used the following code to implement a timer that increments ever 500 ms after the user press the button for startAction:
TextView dayTimer = (TextView)findViewById(R.id.tvDayTimer);
long startTime;
class DayTimer extends TimerTask {
#Override
public void run() {
BBCAndroid.this.runOnUiThread(new Runnable() {
public void run() {
long millis = SystemClock.elapsedRealtime() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
dayTimer.setText(String.format("%d:%02d", minutes, seconds));
}
});
}
};
startDayButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
startTime = SystemClock.elapsedRealtime();
timer.schedule(new DayTimer(), 0,500);
LoginResult.DayState = 1;
startDayButton.setEnabled(false);
endDayButton.setEnabled(true);
}
});
Now my problem is that,if i exit the application the timer stops.How can i make it run even when the user is out of the app?
To sum up ,i need a timer that counts even if the app is closed.
You can start a Service and it will be up and running even if your application is closed.
Here is a good tutorial.
You could create a Service or create a thread in which your timer runs. This wouldn't destroy your timer when you app is closed.
I hope this helps.
I resolved your problem using the life cycle.
If the application is not destroyed you can count time by apllying your code into the onPause or onStop.
But ypu have to advertise the user when he is going to destroy the app.
This was my solution to contiune receiving messages wit my app running in foreground and to avoid an excessive power consumtion.
Read about de lifeCycle here:
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
I hope this can be useful.
I'm using a runnable in my Android app to update a countdown timer, as shown in the code below. It appears to work but I noticed my timer takes a few seconds longer than expected. For example, if it's supposed to count down 3 minutes, it takes 3 minutes and 5 seconds. I tried using a timer in a service to manage the countdown display in the main activity. The timer/service worked as expected.
Why doesn't runnable/postDelayed() run for the correct amount of time? Is postDelayed() timing reliable? The runnable decrements a variable then uses it to update an EditText with setText(). Does setText() take too long (a small fraction of a second), so the runnable really runs every 1.x seconds?
Handler handler = new Handler();
Runnable r = new Runnable() {
public void run() {
// decrement the time remaining and update the display
handler.postDelayed(this, 1000);
}
};
...
// start the runnable
handler.postDelayed(r, 1000);
Your code is kinda sorta designed to be inaccurate because you are not accounting for the time taken by the guts of the runnable. You might get improved results by doing something like
public void run(){
startTime = System.currentTimeMillis();
// compare expectedTime to startTime and compensate
// <guts of runnable goes here>
// now wrap it up...
delay = 1000 - (System.currentTimeMillis() - startTime);
if (delay < 0)
delay = 0;
expectedTime = System.currentTimeMillies() + delay;
handler.postDelayed(this, delay);
}
What about using CountDownTimer? I used this for same tasks several times and haven’t met this kind of problem.