how to create CountDownTimer that execute command every 10 mins - java

I want to make an Android app that starts counting down from 10 mins and when it reaches 0, it should execute a command to send data via internet.
After that it should start all over again from 10 mins. It should keep sending data every 10 mins until I manually stop it.
(I have already created command to send data via internet and it works perfectly, but I don't know how to make the count down timer.)
Thanks in advance!

public class MyCounter extends CountDownTimer
{
public MyCounter(long millisInFuture, long countDownInterval)
{
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish()
{
System.out.println("Timer Completed.");
}
#Override
public void onTick(long millisUntilFinished)
{
//Your function here..
}
}
Before oncreate,
final MyCounter timer = new MyCounter(Long.MAX_VALUE,600000);
In oncreate,
timer.start();

You can use the concept of multi threading in java, make a thread and make it sleep for minutes as it wakes call the code/method in, you can start thread
class SampleThread extends Thread {
#Override
public void run() {
try {
Thread.sleep(600000);
callYourmethodHere();
}
catch (InterruptedException e) {
}
}
SampleThread t = new SampleThread();
t.start();
start the timer when ever required

Related

Replacing CountDownTimer with Handler and Runnable for better performance

I've got game based on CountDownTimer, which is continuously repeating countdowns. This countDown is counting time for user to react on some action related to number, if user reacts onFinish() is called by some clickListener or by itself if the time was up. Depending of succesCondition(), method success or fail is called and those methods are defining if game is still running.
OnCreate
loop = gameLoop(time).start();
MainActivity
public CountDownTimer gameLoop(int time){
return new CountDownTimer(time, time+100) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
if (!Conditions.succesCondition(number)) {
success();
} else {
fail();
}
}
};
}
public void success() {
loop.cancel();
scoreCount++;
animation.start();
}
public void fail(){
loop.cancel();
}
However this timer runs on Main thread and that provides well known issue skipped xx frames, your app might be doing too much work on its main thread and I found that this is common issue for CountDownTimer and replacing it with Handler is a solution.
I can't put this timer in AsyncTask because it performs mainly UI related tasks (TextViews, TextSwitcher, some progressBar etc. in success() method. I didn't put that in code in those methods for more clean view of the main problem. I'm trying to reconstruct CountDownTimer- like concept with handler and runnable to replace my Timer, but I'm actually stuck with nothing. As you can see I'm using only onFinish method, onTick is not necessary.
I suggest using a combination of java.util.Timer, java.util.TimerTask and Activity.runOnUiThread(). First create a Timer and call one of its schedule...()methods. Any action that needs to be done on the main (ui) thread can be wrapped in runOnUiThread(() -> { ...}). Be sure to call cancel() on TimerTask and Timer if those objects are no longer needed. Cancelling the Timer cancels the TimerTask as well.
Here is how this may look like:
public class TimerTaskActivity extends Activity {
Timer timer;
TimerTask timerTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timertask);
...
}
#Override
protected void onStart() {
super.onStart();
timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(() -> {
....
});
}
};
timer.scheduleAtFixedRate(timerTask, 2000, 2000);
}
#Override
protected void onPause() {
super.onPause();
timer.cancel();
}
}
You may handle this situation using AsyncTask as well overriding the onProgressUpdate method.
Here's an example about how you can achieve the behaviour to interact with your main thread from AsyncTask. The example shows the update of a download which can be easily transformed to your specific problem of timer.
Update
In my case almost all code would be in onProgressUpdate, would it
still make any sense?
No, your code will not be in onProgressUpdate. The onProgressUpdate method will only be updating your timer in your UI. As far as I could understand, the success and the fail will be triggered based on user action as well. Then those actions are triggered, you can stop the AsyncTask to update your timer as well. You just need to AsyncTask to update the timer value time to time.
You will get a callback in your Activity when the AsyncTask finishes. See the mNotificationHelper.completed(); function in the above example. When you are notified in your Activity when the timer finishes, you might then execute the following task there.
public void completed() {
if (!Conditions.succesCondition(number)) {
success();
} else {
fail();
}
}
OK. I finally figured out how to handle it with handler (hehe):
public void startGameAction() {
//My game actions
handler = new Handler();
runnable = () -> {
if (!Conditions.succesCondition(number)) {
success();
} else {
fail();
}
};
handler.postDelayed(runnable,time);
}
public void success(){
handler.removeCallbacks(runnable);
handler = null;
scoreCount++;
//other stuff
startGameAction();
}
private void fail() {
handler.removeCallbacks(runnable);
//other stuff
}
onCreate only startGame call, handler and runnable defined as class fields
startGameAction();

Why doesn't countdown timer work on standalone class which is not an activity?

I am trying to use countdowntimer in Android, following is a small testcode to understand its behaviour
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
System.out.println("tick");
}
public void onFinish() {
System.out.println("finish");
}
}.start();
System.out.println("done");
If I place this snippet in MainActivity of my project it runs fine, but not in a standalone class. Why ?
Also, does countdown timer run on main thread itself, or it spawns another thread ?
Your code includes 2 parts:
CountDownTimer cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
System.out.println("tick");
}
public void onFinish() {
System.out.println("finish");
}
};
The first part is instantiating a CountDownTimer object, you can place this code any where, on any thread, because only object was created, it does nothing.
The second part is:
cdt.start();
You should notice that CountDownTimer must be start from Main Thread (call it from onCreate or onResume... of an Activity). So if you place your code in another Class, it is not the problem, you must sure that start() function called on Main Thread.
//Update:
You know, the onTick and onFinish function of CountDownTimer always is called on Main Thread. CountDownTimer will not run any thread.
It's its code:
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
Very simply, CountDownTimer will send a message by a Handler.
And this is Handler:
// handles counting down
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) {
if (mCancelled) {
return;
}
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft);
// take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
// special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
The Handler will send a delay message for calling next onTick() or onFinish(). So it must use Main Thread (or Main Looper). If you want it run in a custom thread, reimplement it in your way :D

Stackoverflow inside thread - stopwatch java

I would like to create a stopwatch as an android app. My problem is that I got a stackoverflow. Basically I have a class Timer and an onCreate method that instatiate it. Thats my implementation:
public abstract class Timer implements Runnable {
private boolean running;
public void start(){
running = true;
this.start();
}
#Override
public void run() {
long milliSeconds = 0;
long seconds = 0;
long minutes = 0;
long baseTime = SystemClock.elapsedRealtime();
while(running){
long time = SystemClock.elapsedRealtime() - baseTime;
long rest = time % 60000;
milliSeconds = rest % 1000;
seconds = rest - milliSeconds;
minutes = time - seconds - milliSeconds;
display(milliSeconds, seconds, minutes);
}
}
public void stop(){
running = false;
}
public abstract void display(long milliSeconds, long seconds, long minutes);
}
And my onCreate method:
public TextView time;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.opslimit);
time = (TextView)findViewById(R.id.textView3);
Timer timer = new Timer(){
#Override
public void display(long milliSeconds, long seconds, long minutes) {
time.setText(minutes + ":" + seconds + ":" + milliSeconds);
}
};
timer.start();
}
Has anyone an idea why I got a Stackoverflow. May be it deals with the display part?
You call start method recursively within itself. Fix it, and you won't get SO exception.
Note, however, that even if you change to :
public void start(){
running = true;
this.run();
}
which will fix stackoverflow, your code will run in a main thread and therefore your app won't work. You have to spawn a new thread.
I really suggest you use CountDownTimer - it will be clean code and less boilerplate threading, check example at the link.
You can, however, make your code work by doing this changes :
make Timer extends Thread instead of implementing Runnable.
change start to :
public void start(){
running = true;
super.start(); // <- note super here
}
Optionally add Override notation to start/stop methods, or rename your stop -> stopTimer

android - Showing variable changes

Ok - I know there has got to be a simple solution to this but for the life of me I can't figure it out.
Programming a very basic android activity to simply iterate through 0-99. I have a textview that I want to display the count. What happens is that it simply stays blank until the end and then shows the ending count (99).
Not sure if a textview is the right way to display or what the answer is. Any help is greatly appreciated. Thanks in advance
Try using code like this in onCreate (where number is defined as a field):
textView.post(new Runnable() {
#Override
public void run() {
number++;
textView.setText("counting: " + number);
if (number < 100) {
textView.postDelayed(this, 50);
}
}
});
Edit: code was edited as View classes have post and postDelayed, which propagates call to Handler instance they have internally.
You need to read a bit about Handler class.
Warning: this code leaks Activity for the time of approximatelly 5 seconds and should not be used directly in production code. You need to remove Runnable from the message queue at the appropriate time (maybe in onDestroy, but it depends on your needs).
View.removeCallbacks for anti-memory-leak.
My guess is that your onCreate() has code like this:
for (int i=0;i<100;i++) {
tv.setText(String.valueOf(i));
Thread.sleep(100); // or something to delay for a bit
}
That will give you the output that you are describing.
As with many GUI frameworks, Android's UI is event-driven. Calling setText() does not update the screen. Rather, it puts a message on a queue, asking for the screen to be updated. That queue is processed by the main application thread... the same thread that is calling onCreate() in the first place. Hence, what you are doing is queuing up 100 setText() calls, none of which will be processed until your loop is complete. Applying the 100 of them takes very little time, giving the visual result of only seeing the last change.
User a timer scheduled at a fixed rate. Increment a counter every second. Set the text on the UI thread. cancel the timer when required.
public class MainActivity extends Activity {
TextView _tv;
Timer _t;
int _count=0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_tv = (TextView) findViewById( R.id.textView1 );
_t = new Timer();
_tv.setText(""+_count);
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
_count++;
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
_tv.setText(""+_count);
if(_count==99)
{
_t.cancel();
}
}
});
}
}, 1000, 1000 );
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
_t.cancel();
}
}
Use a countdown timer, in below code, onTick() will get called every second, here you can display/update your number each second.
set interval according to your need. Its in mili seconds.
public class TimerActivity extends Activity {
private final long startTime = 100 * 1000;
private final long interval = 1 * 1000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
countDownTimer = new MyCountDownTimer(startTime, interval);
countDownTimer.start();
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
text.setText("Time's up!");
}
#Override
public void onTick(long millisUntilFinished) {
text.setText(100 - millisUntilFinished/1000);
}
}
}

Base Activity with runnable

Intro: I have made a Base Activity to extend my other activities to. I have overriden several methods with runnables in the function bodies, for example:
#Override
protected void onStop(){
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
BaseActivity.super.onStop();
}
}, Fade.fadeDuration);
}
However, I get a SuperNotCalledException when I try to run the app. If I take the super.onStop() out of the runnable, I get no exception whatsoever.
Question: How do I call the super.onStop from a runnable in a base activity without causing a SuperNotCalledException?
Additional info: I am trying to add a fadeoutanimation which only fades out certain views. This takes about 700ms so I need to delay the onStop for 700ms as well. The problem is that this is a hassle to code in every activity. I want to make a base activity so I don't have to worry about the fading in every single activity.
If you are trying to simply delay execution of the super.onStop I would use a CountDownLatch.
Maybe something like this :
private void CountDownLatch latch;
private void long latchWait = 10L; // seconds
private void TimeUnit latchWaitUnit = SECONDS;
#Override
protected void onStop(){
try{
this.latch.await(this.latchWait, this.latchWaitUnit);
catch(InterruptedException e){
// Handle
}finally{
super.onStop();
}
}
public void startLatch(long wait){
this.latch = new CountDownLatch(1);
this.latchWait = wait;
}
public void releaseLatch(){
this.latch.countDown()
}
I did not test this code.

Categories