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.
Related
I am building an app for video editing...
I want to give some free minutes for 1st time using of app . User can edit the videos until the completion free minutes .
These minutes count based on duration of video which is editing..
After that they have to purchase for further any duration of videos..?
How can I limit user to use some until free minutes?
Till now I didn't used any online service in my app. Everything worked on device.
Any way to implement it on offline.?
If not possible..
What can I do to tackle it..?
I not a native English speaker..
Try to understand... :)
This is a timer that will trigger when no time is left.
It works completely offline .
This goes in the Class outside any other method where you usually declare your variables: (Note that you can set the time you want in millis. I chose 10000ms so 10 seconds as an example)
private CountDownTimer timer;
private long secondsLeft = 10000; // how much milliseconds of
// free time you want to have
//
And this goes where you want to start the time.
timer = new CountDownTimer(secondsLeft, 1000) {
public void onTick(long millisUntilFinished) {
secondsLeft = millisUntilFinished/1000;
}
public void onFinish() {
// The time is up! User has spent the time
}
}.start();
Then add these (or if you already have these methods then add the code in them to your ones.
#Override
protected void onPause() {
super.onPause();
timer.cancel();
}
#Override
protected void onResume() {
super.onResume();
timer = new CountDownTimer(secondsLeft, 1000) {
public void onTick(long millisUntilFinished) {
secondsLeft = millisUntilFinished/1000;
}
public void onFinish() {
// The time is up! The user has used the app for your amount of time
}
}.start();
}
Note: To make it survive an app restart or a phone restart you have to save "secondsLeft" to your device and load it when the app starts.
I need to send a SMS in a future time, i.e. in 5 minutes, and to show in the UI the remaining time in the format 00:00.
My first choice was using android-alarm, but I dont know how to show in the layout the countdown.
Next, I tried to use a chronometer, and use the view of the object, but the time is always up, so i'd need to make a lot of math operations to refresh the view.
Finally I've used a CountDownTimer, and i show in a TextView the elapsed time.
That is the best choice?
Here is a short of code:
public void startCountDown(View v) {
if (!activedCountDown) {
activedCountDown = true;
final TextView mTextField = (TextView) findViewById(R.id.mTextField);
EditText text = (EditText) findViewById(R.id.etMinutos);
String mins = text.getEditableText().toString();
futureTime = Integer.parseInt(mins) * 60000;
isTheFinalCountDown = new CountDownTimer(futureTime, interval) {
#Override
public void onTick(long millisUntilFinished) {
if (millisUntilFinished < 60000) {
mTextField.setText("00:" + millisUntilFinished / 1000);
} else {
//TODO parse the textfield to show minutes and seconds
}
}
#Override
public void onFinish() {
//TODO: launch SMS
mTextField.setText("Send SMS now");
activedCountDown = false;
}
}.start();
}
}
To show user time remaining you may use the countdown timer
BUT FOR SENDING SMS
I will strongly discourage you to use it, you must use the the Alarm/Broadcast reciever because your activity variables might get freed from memory as Android OS needs memory if other apps are running.
See this for detail, it happened to me.
I'm in the process of designing a chronometer / countdown timer app for Android 2.2 and would like one button press to start both the chronometer and the timer simultaneously. So, ideally, I'd like the seconds (time) on both the chronometer and timer to change at the same instance. (The timer will be counting down even as the chronometer is counting up). Since I'm using the chronometer and timer functionality provided by Android, I wrote the following piece of code when the user presses the 'Start' button
private boolean mStartPressedOnce = false;
long mTimeWhenStopped = 0;
Chronometer mChronometer;
MyCounter mCounter;
...
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.StartButton:
// Perform some initialization for the chronometer depending
// on the button press
if (mStartPressedOnce == false) {
mChronometer.setBase(SystemClock.elapsedRealtime());
} else {
mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped);
}
// Perform the initialization for the timer
mCounter = new MyCount(45000, 1000);
// Fire up the chronometer
mChronometer.start();
// Fire up the timer
mCounter.start();
break;
case R.id.ResetButton:
// Reset the chronometer
mChronometer.setBase(SystemClock.elapsedRealtime());
mTimeWhenStopped = 0;
break;
case case R.id.StopButton:
mStartPressedOnce = true;
// Stop the chronometer
mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime();
mChronometer.stop();
break;
}
...
public class MyCounter extends CountDownTimer {
#Override
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
// Nothing to do here
}
#Override
public void onTick(long millisUntilFinished) {
long seconds = (long) (millisUntilFinished / 1000);
long minutes = (long) ((millisUntilFinished / 1000) / 60);
long hours = (long) (((millisUntilFinished / 1000) / 60) / 60);
// Do some formatting to make seconds, minutes and hours look pretty
// Update the timer TextView
(TextView) findViewById(R.id.CountDownTimerTextView))
.setText(hours + ":" + minutes + ":" + seconds);
}
}
Though it looks like the seconds on the chronometer and timer are in sync initially, after a short time, they seem to go off and the second updates for both occur at different times.
Was wondering what I could do to fix this. I did come across - and read this thread
Running multiple AsyncTasks at the same time -- not possible?
I realize that there may be a design change needed but I'm not sure exactly what needs to be done.
Edit: Included types for chronometer and timer and method for calculating time using Chronometer - per jolivier and njzk2's suggestions
You can retrieve the current time with System.currentTimeMillis(), store it into a variable and forward it to both mChronometer and mCounter, so that they use the same time reference although their task started at different time.
Edit: with the given types, the android documentation about Chronometer will tell you that you can use elapsedRealTime to achieve what I said.
CountDownTimer does not have this and its start method is final so you may want to use another implementation, a better view of your use case might help us.
Basically, wanting two threads to perform an action at the same millisecond is never a good idea, one of them will serve as the clock and the other one must be a slave and listen to the clock.
So, after mulling over this for some time and going off of the suggestion jolivier so generously shared with us, I realized that there exists a method called onChronometerTick which is called every time there is chronometer tick (every second, in this case). So, I thought of subtracting 1000 milliseconds from the counter every time the method is called and update the timer display accordingly. I got rid of the Android timer piece (CountDownTimer) completely. I figured this would be a nice way to have both displays update at the same time. It's also a simple implementation of a timer.
I'm happy to report that it seems to work well. Both the timer and chronometer displays indeed update at the same time. So, the original question looks like it's answered. Unfortunately, I ran into an off-by-two error on the timer front that I fixed with an ugly hack. I'm posting what I have so far. Any suggestions on how to fix the hack or improve the code are welcome. Note that I have commented the code to try to make it easy to understand what's been done.
Edit for bug: One more thing I noticed is that after around 10 minutes or so the chronometer and timer are off by one second. More precisely, the timer is behind the chronometer by one second. Not yet sure why this happens.
private boolean mStartPressedOnce = false;
long mTimeWhenStopped = 0;
Chronometer mChronometer;
long millisUntilFinished = 0;
boolean firstPassOver = false;
int counter = 0;
...
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.StartButton:
// Perform some initialization for the chronometer depending
// on the button press
if (mStartPressedOnce == false) {
mChronometer.setBase(SystemClock.elapsedRealtime());
} else {
mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped);
}
// Fire up the chronometer
mChronometer.start();
break;
case R.id.ResetButton:
// Reset the chronometer
mChronometer.setBase(SystemClock.elapsedRealtime());
mTimeWhenStopped = 0;
break;
case case R.id.StopButton:
mStartPressedOnce = true;
// Stop the chronometer
mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime();
mChronometer.stop();
break;
}
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stop_watch);
mChronometer = (Chronometer) findViewById(R.id.StopWatchTextView);
// Initialize the number of milliseconds before the timer expires (
// set the timer) - in this case to 46 seconds
millisUntilFinished = 46000;
// Display how many seconds remain before the timer expires
((TextView) findViewById(R.id.CountDownTimerTextView)).setText(hours
+ ":" + minutes + ":" + millisUntilFinished / 1000);
// In line with the suggestion provided by jolivier - make the timer
// the slave and update its display every time the chronometer
// ticks
mChronometer
.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
// Update the display for the chronometer
CharSequence text = chronometer.getText();
chronometer.setText(text);
// Update the display for the timer
// !!! BUG !!!
// Looks like onChronometerTick is called at the 0th second
// and this causes an off by two error if a count down timer
// is being implemented. Fixed it with this hack. There's gotta
// be a more elegant solution, though.
if(counter >= 2) {
millisUntilFinished1 = millisUntilFinished1 - 1000;
counter = 2;
}
counter++;
if (millisUntilFinished >= 0) {
long seconds = (long) (millisUntilFinished / 1000);
long minutes = (long) ((millisUntilFinished / 1000) / 60);
long hours = (long) (((millisUntilFinished / 1000) / 60) / 60);
// Do some formatting to make seconds, minutes and hours look pretty
// Update the timer TextView
((TextView) findViewById(R.id.CountDownTimerTextView))
.setText(hours + ":" + minutes + ":"
+ seconds);
}
}
});
// Other code
...
}
I am working on a mini game for Android. I am using this code to create a 3 minute timer that pauses when the game is paused:
class update extends Thread{
#Override
public final void interrupt(){
super.interrupt();
}
#Override
public void run(){
try{
while(true){
sleep(50);
iTime++;
if(iTime>=3600)
bEnd = true; //finish
postInvalidate();
}
}catch(InterruptedException e){
}
}
}
update thread = null;
3600 = 20*3*60
The timer finishes in the emulator within about 5 minutes, and in the Galaxy Tab after about 1.5 minutes.
Why doesn't it always take 3 minutes? How do I ensure that it finishes within 3 minutes?
How about using the Android CountDownTimer class?
// 30 second countdown
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
I am not sure what are you doing in the postInvalidate() but maybe you can do something with AlarmManager and a service. You could create a task that will run in 3 minutes from now, and it will execute the service which, in your case, will invalidate the game.
I've seen many questions that were trying to handle timeouts with sleep method and I believe Android doesn't guaranteed that it will work that way.
Post back if you need help creating the service or running something with AlarmManager. I answered a question about it a couple of days ago.
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);
}