I have an application in which I'm displaying a chronometer to the user for what he's doing.
Whenever the activity goes to the background (wether by home button, or back) I save that time (in seconds) and when the activity is brought back, I want to continue the chronometer running from the same time. The user might select a different item from the list, and the time is different, and also he might turn off the phone...
I can save the time of the chronometer, however I can't set it with a start time.
From the Chornometer API, the method setBase() states:
Set the time that the count-up timer is in reference to.
On my understanding, this means that if I set this value to currentTime, it'll start counting with 0.
Now, if I want it to start with the value 17s I thought about setting the base to the currentTime less the time 17 seconds ago. So something like:
setBase(system.currentTimeMillis() - (17 * 1000)).
However this doesn't work, and the it starts always with 0!
I read a few other threads around here, and none of the answers helped. It always starts with 0!
Thanks in advance.
I think you're going to have to keep track of some time marks yourself.
Chronometer myChrono;
long baseTime;
long stopTime;
long elapsedTime;
When you set the base time, you want to use:
baseTime = SystemClock.elapsedRealtime() - stopTime;
myChrono.setBase(baseTime);
When you want to see how much time has passed, use:
elapsedTime = SystemClock.elapsedRealtime() - myChrono.getBase();
Take a look at the SystemClock doc.
setBase(system.currentTimeMillis() - (17 * 1000))
Should be changed to
setBase(SystemClock.elapsedRealtime() - (17 * 1000))
In general:
mChronometer.setBase(SystemClock.elapsedRealtime() - (nr_of_min * 60000 + nr_of_sec * 1000)))
Hopefully this will save lots of u folks some time :)
Related
Situation:
I need to create a program that shows current date and updates some date(that is NOT CURRENT date,it is past date) according to current time(for example after 23:59,date refreshs). In other words,it is simple application,that shows date in the past and time.
What did I try?
I have found TextClock for this. It can show current time,but I cannot track over it.
So what can I do? I need to create my own clock class or use Timer and TimerTask? Do I need a Service?
I think, if I understand you correctly, you're on the right path. I wasn't familiar that there was even a TextClock view, but it looks pretty basic and will just work for displaying the current time.
Instead, maybe use a TimerTask to update the UI every second, or so, and set one TextView with the current time and another with your other time that's an offset of the current time (current = new Calendar(); current.add(Calendar.MINUTE, 1); )
You could use TimerTask, and that'd be pretty easy compared to rolling your own thread or using an AsyncTask. Get the current time, set it to one text view, manipulate that time variable and set it to the other text view.
The app is a sports timer for cycling, skiing etc, where racers start at regular intervals. e.g. 1 minute.
In my implementation of OnChronometerTickListener I notice that the calls occur at intervals significantly longer than 1000 mS. I use the elapsed time (between the Tick and the Chronometer's base) to count down the last 5 seconds for each interval. Due to the late callback, I can get ticks at, say,
55,500
56,600
57,750
58,870
59,980
61,110
I can therefor skip a whole second when I use m_Elapsed % 1000.
I have even seen the text in the Chronometer get behind and have to skip a second.
I have no problem with accuracy when I do calculations based on the Chronometer's base time and current system time.
Do I have to write my own Chronometer using finer callbacks?
Or is there some other fix?
Ive got an app with a class that implements Runnable. Where a thread is started and the run() methid overridden. This runs my graphics.
1.st question : how often is the run() called upon? i havent set a time for this so it must be a default value?
2.nd question : i want stuff to be done after a certain amount of time (2min,5min,10min) etc. What would be the best way to go about doing this, i was thinking about using an int as an counter and once it hits a specific value does what i want.
1.st question : how often is the run() called upon? i havent set a time for this so it must be a default value?
The run() method in your Thread is called when you call it eg. yourThread.start();
2.nd question : i want stuff to be done after a certain amount of time (2min,5min,10min) etc. What would be the best way to go about doing this, i was thinking about using an int as an counter and once it hits a specific value does what i want.
There are to options. Either you could call Thread.sleep() method (NB: Never do this in your UI thread).
Or you can do it the way you described above. So in your run() method you would have a while() loop and check on every iteration if the difference of the lastUpdate and the current time in milli seconds is bigger than the wanted period eg. 2 min, 5 min or 10 min.
I hope this helps.
Regarding question 2 - use ScheduledExecutor
1.st question : how often is the run() called upon?
You can find out for yourself, put this at the start of your Runnable:
Log.v("Running Runnable", System.currentTimeMillis() + "");
2.nd question : i want stuff to be done after a certain amount of time (2min,5min,10min) etc.
Extend a HandlerThread (it initializes the Looper for you!), add a Handler as a class variable, and use the Handler's postDelayed() or postAtTime() methods.
The exact amount of time in between calls to run() depends on the processor. The time between each call is the sort of thing that's really visible by the nanosecond. If you're trying to create a timer, I'd recommend using System.currentTimeMillis(), calling it in the run() method, and once the difference is greater than or equal to 1000 milliseconds, the actual timer decrements by one. This will keep track of seconds, and you can use it as a base for minutes and generating other events at specific times.
How to start the chronometer with a specific time other than default 00:00? Is it possible to set chronometerObj.setBase(startTime) ?
ch.setBase(SystemClock.elapsedRealtime()-anylongvalue);
ch.start(); can I set start time, if I put anylongvalue?
In general:
mChronometer.setBase(SystemClock.elapsedRealtime() - (nr_of_min * 60000 + nr_of_sec * 1000)))
Chronometer object, when instantiated, defaults to the base time being set to now ('now' as in the value you get from SystemClock.elapsedRealtime()).
You can change the base time (00:00 time) by calling setBase(<some other value>).
Presumably, although I haven't tried the experiment, you could see the elapsed time since last system boot using setBase(0).
So you can use chronometer to see the elapsed time since any arbitrary call you made in the past to SystemClock.elapsedRealtime(). The trick is that you need to have stored that value somewhere you can dependably get it back despite app and phone state changes. (See Android: chronometer as a persistent stopwatch. How to set starting time? What is Chronometer "Base"? for example.)
Many answers suggest persisting that arbitrary time-in-the-past in an intent. but, at best, this only keeps the timer counting up while the phone stays on.
I already am using a database and store my starting time in there. I created a one-column table for it and store a single record in it. My starting time for the chronometer survives a phone reboot.
I have a puzzle game for android. When the puzzle starts I take the current time:
long startTime = System.currentTimeInMillis()
When the player completes the puzzle, I take the time again, subtract the starting time and work out the elapsed time. This is all ok.
My problem is what to do when the application is interrupted. For example by a phone call. At the moment, the puzzle remains in it's previous state automatically (as it is in a view). However, the calculation completionTime = currentTime - startTime will now be invalid.
I have tried saving the elapsed time using onSaveInstaceState(Bundle). However its counterpart, onRestoreInstanceState(Bundle) is not called when re-entering the app. Rather, the onResume() method is called instead? I have read this is because the app has not been 'killed', rather it is still in memory. In the case of a 'kill', I'd imagine the state of the View will also be lost? I don't think it's terribly necessary to keep track of the view in this case, so I won't worry about the time either.
Is there a way to read a bundle from onResume(), should I just implement a shared preference?
I'd like to avoid updating the elapsed time in the game loop as this seems inefficient.
I would advice not using a SharedPreference at all.
You will only need 2 fields: startTime and elapsedTime
When the player starts, initialise elapsedTime to 0 and startTime to System.currentTimeMillis()
When onPause() is called, initialise elapsedTime using
elapsedTime = elapsedTime + (System.currentTimeMillis() - startTime);
When onResume() is called, initialise startTime to System.currentTimeMillis()
When the player is done, the time is
elapsedTime = elapsedTime + (System.currentTimeMillis() - startTime);
Please, if the logic has a flaw, comment (:
Note: There exists a way to use only one field.! But we'll keep that for the reader to discover.
shared preference seems a better idea to me.
calculate the time difference in onPause() , when the game goes to background, assuming user is already playing game. Add this difference to the previous time in the shared preference and store it again.
start the clock again on onResume() and repeat step 1 if necessary.
I hope you get the idea.