In my app, I implement CountDownTimer in my listview as following:
OrdersCountDownTimer.java
public class OrdersCountDownTimer extends CountDownTimer {
private OrdersAdapter adapter;
public OrdersCountDownTimer(long millisInFuture, long countDownInterval, OrdersAdapter adapter) {
super(millisInFuture, countDownInterval);
this.adapter = adapter;
}
#Override
public void onTick(long millisUntilFinished) {}
#Override
public void onFinish() {
adapter.decTime();
adapter.notifyDataSetChanged();
this.start();
}
}
OrdersActivity.java
timer = new OrdersCountDownTimer(ONE_SECOND, ONE_SECOND, adapter);
So, I'm decrementing the value in my Order object upon every tick my timer finishes.
The problem is that this is running in my main thread, which means when my app goes to the background or the screen is locked, the timer is paused as well.
I would like to keep the timer running at all times. Is there a way to do this?
Related
The project i'm working on is an quiz with a timer on each question. for 30 seconds. I noticed that if you finish the test before the timer runs out, the timer doesn't stop running. So if you head on to another test, the notification that you haven't finished the test will popup and override the current activity. I tried using the cancel() method, but i'm sure I misplaced it.
Here is a snippet of the MyCountDownTimer Class
public MyCountDownTimer(TextView textCounter, long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.textCounter = textCounter;
}
#Override
public void onTick(long millisUntilFinished) {
textCounter.setText(String.valueOf(millisUntilFinished / 1000));
}
#Override
public void onFinish() {
Intent retryIntent = new Intent(textCounter.getContext(), Retry.class);
if (textCounter.getContext() instanceof Test1){
whichTest = 1;
retryIntent.putExtra("whichTest",whichTest);
}
textCounter.getContext().startActivity(retryIntent);
}
This is a snippet of the Activity that implements the method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_page);
textCounter = ((TextView)findViewById(R.id.textCounter));
myCountDownTimer = new MyCountDownTimer(textCounter, 29000, 1000);
myCountDownTimer.start();
textCounter.setText("");
myCountDownTimer.onTick(29000);
}#Override
public void onClick(View v) {
if (questionIndex == questions7.length){
myCountDownTimer.cancel();
Intent intent1 = new Intent(Test1.this, UsersAnswers1.class);
intent1.putExtra("usersAnswers1", usersAnswers1);
intent1.putExtra("isATOF1", isATOF1);
intent1.putExtra("score1S", score1S);
startActivity(intent1);
}
}
Override onStop method of your activity and use code like
#Override
protected void onStop() {
myCountDownTimer.cancel();
super.onStop();
}
Hence whenever your activity goes in background it will cancel any timer associated with current activity.
In my onCreate method in my activity i call a method from an object and pass the methods value as 1 which means to start a timer in the objects class. However I want to stop the timer whenever the app closes, loses focus or someone pressed the back button on their device and exited the app. I tried doing this below my onCreate method with an onPause, onStop, onDestroy and entered the methods value as 2 for the object which means to cancel the timer. However my problem is that whenever someone presses the back button on their device and then goes back in to the app the same timer is running twice because the app did not cancel the timer in the onStop, onPause or onDestroy. Why didn't the onStop, onPause and onDestroy stop the timer and how do i make it stop the timer so two arent running when the app is reopened?
Activity below
Ship mShip = new Ship(0,0,0);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mShip.timerStart(1);
}
#Override
public void onPause()
{
super.onPause();
mShip.timerStart(2);
}
#Override
public void onStop()
{
super.onStop();
mShip.timerStart(2);
}
#Override
public void onDestroy()
{
super.onDestroy();
mShip.timerStart(2);
}
Ship Class below
public static int counter = 0;
public static int counterPerSec = 5;
TimerClass startTimer = (TimerClass) new TimerClass(2000,1000)
{
#Override
public void onFinish() {
counter += counterPerSec;
this.start();
}
};
public void timerStart(int x) {
if(x == 1)
{
startTimer.start();
}
if(x == 2)
{
startTimer.cancel();
}
}
Timer Class
public class TimerClass extends CountDownTimer {
public TimerClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override // when timer is finished
public void onFinish() {
this.start();
}
#Override // on every tick of the timer
public void onTick(long millisUntilFinished) {
}
}
I can not see, why your timer is not canceled. But there is another bug in your code: You can not pause and resume a countdown timer by calling resume and start.
If your time gets canceled, you should save the old timer vaules. And if your timer has to be resumed, you can create a new timer with the old timer values. See: Android: How to pause and resume a Count Down Timer?
To your question: Can you debug and check if onPause, onStop, onDestroy is called? Is there any exception thrown? Do you have any compile warnings?
Last important question: How do you know that two timers are running?
Well, I think I can correctly assume that onPause, onStop, and onDestroy are executing, so I would venture to guess that there is a bug in your TimerClass class.
I want to stop CountDownTimer and to restart it, with time when it stopped. I have this code in class CountDownTimer
public class MyDownTimer extends CountDownTimer{
long mills;
public MyDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.mills=millisInFuture;
}
#Override
public void onFinish() {
GameScreen.showWindow("Time is over","Sorry, time is Over, you lose");
}
#Override
public void onTick(long millisUntilFinished) {
mills=millisUntilFinished/1000;
GameManager.time= millisUntilFinished/1000;
}
}
and Dialog class, he must to showing, when user click in button 'pause'.
Dialog code, as you can see, i start new CountDownTimer in this code
public static void showWindowPause(final MyDownTimer dTime){
final Dialog wdialog= new Dialog(context);
wdialog.setContentView(R.layout.dialog_window);
wdialog.setTitle("title");
TextView text=(TextView)wdialog.findViewById(R.id.txtFirstWord);
text.setText("mainText");
Button dialogButton=(Button)wdialog.findViewById(R.id.button1);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
wdialog.dismiss();
dTime.start();
}
});
wdialog.show();
}
and method, where I stoping CountDownTimer and show Dialog window.
long stime =dTime.mills;
dTime.cancel();
dTime=null;
dTime= new MyDownTimer(stime,1000);
GameScreen.showWindowPause(dTime);
when i click button in Dialog window, i see new Dialog, which created in method
MyDownTimer.onFinish()
But if I change line
long stime =dTime.mills;
on
long stime =5000;
CountDownTimer restarts,and all normal.
where i made mistake?
Your question is really confusing , but I THINK I found something that doesn't make sense.
public void onTick(long millisUntilFinished) {
mills=millisUntilFinished/1000;
GameManager.time= millisUntilFinished/1000;
}
I think it should be
mills=millisUntilFinished - 1000;
edit: If you are actually converting millseconds to seconds, then you'll need to do
long stime =dTime.mills*1000;
I am new to android (and not so hot with it, but trying to learn).
I am creating an application that has a number of various buttons that start countdown timers when they are clicked.
On the activity that has these buttons the following code is used to start the timer:
//Button 1 Start On Click
final CountDown buttonOneTimer = new CountDown(15000,1000);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonOneTimer.start();
}
});
//Button 2 Start On Click
final CountDown buttonTwoTimer = new CountDown(15000,1000);
buttonTwo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonTwoTimer.start();
}
});
my CountDown class looks like this:
public class CountDown extends CountDownTimer {
public CountDown (long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
System.out.println("Timer Completed.");
****NAMEOFTHEBUTTONCLICKED****.setText("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished) {
****NAMEOFTHEBUTTONCLICKED****.setText((millisUntilFinished/1000)+"");
System.out.println("Timer : " + (millisUntilFinished/1000));
}
}
I am trying to get the name of the button pressed into the class so I can set the text on the button to countdown.
I'm sure I am doing all sorts of things wrong or there may be better ways to do it - so if you see areas where I could improve - feel free to critique me!
I read over the tutorial here however it has an 'inner class' (I believe that is what it is called?) inside the current class. A friend of mine said that's very rarely done and to just create a separate class such as CountDown. If I do it the same way as in the tutorial I can get the timer to work (by hardcoding the buttons name where it says *NAMEOFTHEBUTTONCLICKED* above, which means it only works for that button) - but I still need to figure out how to pass that class the buttons name so I don't have to write a separate class for each timer.
Would that be done through Extras? I have had a hard time finding any more info to my specific issue. Any help is appreciated!!
Try passing off the button instance to the Timer:
public class CountDown extends CountDownTimer {
Button button;
public CountDown (long millisInFuture, long countDownInterval, Button button) {
super(millisInFuture, countDownInterval);
this.button = button;
}
#Override
public void onFinish() {
System.out.println("Timer Completed.");
button.setText("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished) {
button.setText((millisUntilFinished/1000)+"");
System.out.println("Timer : " + (millisUntilFinished/1000));
}
}
Then call like this:
//Button 1 Start On Click
final CountDown buttonOneTimer = new CountDown(15000,1000,buttonOne);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
buttonOneTimer.start();
}
});
I am working on a layout which shows a tab like structure on bottom of the layout. Which I need to show on double tap and then hide it after 5 sec. So I am using this countdown timer:
public void timer()
{
cdt=new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
System.out.println("Timer Working"+millisUntilFinished+"");
}
#Override
public void onFinish() {
System.out.println("Finished");
main =(LinearLayout)findViewById(R.id.parent);
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)main.getLayoutParams();
mlp.height=420;
set_up_views();
find_module();
tl.setVisibility(View.INVISIBLE);
}
}.start();
}
But I dont know how to stop and restart this timer. How can I do?
I suggest you not to Use CountDownTimer for this case.
Use Handler.postDelayed(Runnable runnable, long delay)
public class yourActivity extends Activity
{
public Handler handler = new Handler();
...
public void hideAfter5Sec()
{
handler.postDelayed(new Runnable()
{
View view = findViewById(view_to_hide);
view.setVisibility(View.INVISIBLE);
}, 5000);
}
}
postDelayed will execute that code after 5Sec.
EDITED:
postDelayed will be call only once after 5 Sec through Lopper.loop(). If there are multiple call to hideAfter5Sec() then only you will get multiple call to postDelayed.
If you have multiple call hideAfter5Sec() i dont think there is any wrong because hideAfter5Sec() is just hidding it. so if it one or many your view will be hidden.
If in case you want to hide only in the last call of hideAfter5Sec() use this variant.
public class yourActivity extends Activity
{
public Handler handler = new Handler();
public long lastHideAfter5Sec = 0L;
...
public void hideAfter5Sec()
{
lastHideAfter5Sec = System.currentTimeMillis();
handler.postDelayed(new Runnable()
{
if(System.currentTimeMillis() - lastHideAfter5Sec < 5000)
return;
View view = findViewById(view_to_hide);
view.setVisibility(View.INVISIBLE);
}, 5000);
}