I've crated Log in screen, and if user mistake 3 times i want to show timer of 2 min. I want that timer to be visually shown on the screen. I'll try this code and it's work, but I don't know how to display timer on screen.
Handler handler = new Handler();
long waitingTime = 2 * 60 * 1000; // 2 min
handler.postDelayed(new Runnable() {
#Override
public void run()
{
//Do something after 2 min
}
}, waitingTime);
You need to have Handler called every second and update the UI during every pass. When you reach 2 mins you can cancel the handler.
Code should be like this:
final Handler handler = new Handler();
//class variable
count = 0;
handler.post(new Runnable() {
#Override
public void run() {
updateCounter(count++);
if(count < 120) {
handler.postDelayed(this, 1000);
}
}
});
And function to update counter:
private void updateCounter(final int count) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// you have the seconds passed
// do what ever you want
}
});
}
you need use runOnUiThread(Runnable action)
Related
Hi I am new to android delveloping and I am curently making a simple game that tests your reflection when a certain color changes, to test what I have learned so far but I cant solve a problem that came up.
Alright, first I will explain how the game works:
When you tap the screen there is a random delay and after that you need to tap the screen again as quick as possilbe to get the best score, and if you tap earlier than when the delay is over the game stops and tells you to try again.
My problem is that when I tap for the second time no matter if that is after or erlier the delay it repeats a part of a code and I cant figure out why.I posted my code that is relevant to this below.Also if you need any decleration let me know!
P.S I thing that it has somenthing to do with the handlers but i'm not sure.
final Random random = new Random();
final int randomNumber = random.nextInt(10) + 1;
bestScoreView.setText("best score " + bestTime + " ms");
mainThing.setText("Tap to start");
mainThing.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
randomTimeDelay = randomNumber * 1000;
if (previousTapDetected){
mainThing.setText("You taped too fast");
mainThing.setBackgroundColor(ContextCompat
.getColor(getApplicationContext(), R.color.red));
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mainThing.setText("Try again");
}
}, 750);
}else if (previousTapDetected = true){
mainThing.setText("Wait for the color to change");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
previousTapDetected=false;
mainThing.setText("Tap now");
startTime = System.currentTimeMillis();
mainThing.setBackgroundColor(ContextCompat
.getColor(getApplicationContext(), R.color.red));
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mainThing.setText("You scored " + score + " ms");
mainThing.setEnabled(false);
}
}, 500);
}
}, randomTimeDelay);
endTime = System.currentTimeMillis();
score = endTime - startTime;
if (bestTime > score) {
bestScoreView.setText("Best score: " + score + " ms");
bestTime = score;
} else if (bestTime < score){
bestScoreView.setText("Best score " + bestTime + " ms");
}
}
}
});
As per the docs
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
And, in your code, you are trying to manipulate the UI elements, so the Handler should be created on the UI Thread
Handler handler = new Handler();
mainThing.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
randomTimeDelay = randomNumber * 1000;
if (previousTapDetected){
mainThing.setText("You taped too fast");
mainThing.setBackgroundColor(ContextCompat
.getColor(getApplicationContext(), R.color.red));
handler.postDelayed(new Runnable() {
#Override
public void run() {
mainThing.setText("Try again");
}
}, 750);
I've been looking for a way to create a timer that counts up in the format of mm:ss:SS and cannot for the life of me find a way of doing it. I had a timer running through a Handler and a Runnable but the timing was off and it took around 2.5 seconds to do a "second". I'll also need this timer be able to countdown too!
Can anyone give me any resources or code snippets to research on this as it is a big part of the app I'm coding.
Here's a bit of the code that I was using
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
/* do what you need to do */
testMethod();
/* and here comes the "trick" */
handler.postDelayed(this, 10);
}
};
public void testMethod()
{
// Log.d("Testing", "Test");
final TextView timeLabel = (TextView)findViewById(R.id.timeString);
count++;
seconds = (int)(count / 100);
final String str = ""+count;
runOnUiThread(new Runnable() {
public void run() {
timeLabel.setText("" + seconds);
// Log.d("Time", "" + count);
}
});
}
Ta!
Make small custom class by extending CountDownTimer class and then add integer or long type and then increment it, since each tick is 1 second (integer) in this case
public class TimeCounter extends CountDownTimer {
// this is my seconds up counter
int countUpTimer;
public TimeCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
countUpTimer=0;
}
#Override
public void onTick(long l) {
//since each tick interval is one second
// just add 1 to this each time
myTextView.setText("Seconds:"+countUpTimer);
countUpTimer = countUpTimer+1;
}
#Override
public void onFinish() {
//reset counter to 0 if you want
countUpTimer=0;
}
}
TimeCounter timer = new TimeCounter(whenToStopInSeconds*1000, 1000);
This should get you started, in your case use long instead integer
countUpTimer = countUpTimer+1000 countUpTimer type and do time parsing as suits you
Rather than using the Handler, I'd recommend using the java.util.Timer and the java.util.TimerTask APIs. Use the Timer's void scheduleAtFixedRate() method which basically executes tasks after a fixed interval of time. The Handler's method most likely uses a fixed-delay execution.
Timer's Documentation
TimerTask's Documentation
I am having trouble delaying the method assign_backgrounds() within a for loop. I am trying to create a Simon says game, but instead of delaying and showing the next button that "Simon" presses, it shows all the buttons at once. Any help here would be greatly appreciated. Thanks.
boolean simonsTurn = true;
int x = 4;
int s;
int delay = 1000;
int array_values[] = new int[]{1,2,3,4};
public void simonSays() {
// running = true;
if (simonsTurn == true) {
go();
for (int i = 0; i < x; i++) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
go();
}
}, 1000);
}
}
}
public void go(){
s = random_int_between(0,3);
assign_backgrounds(array_values[s]);
}
public void assign_backgrounds( int array_values ){
Handler handler = new Handler();
if( array_values == 1){
button1_.invalidate();
button1_.setBackgroundResource(R.drawable.goatclicked);
button1_.refreshDrawableState();
handler.postDelayed(new Runnable(){
public void run(){
button1_.invalidate();
button1_.setBackgroundResource(R.drawable.goat);
button1_.refreshDrawableState();}}, 1000);
}
else if( array_values == 2){
button2_.invalidate();
button2_.setBackgroundResource(R.drawable.pigclicked);
button2_.refreshDrawableState();
handler.postDelayed(new Runnable(){
public void run(){
button2_.invalidate();
button2_.setBackgroundResource(R.drawable.pig);
button2_.refreshDrawableState();}}, 1000);
}
else if( array_values == 3){
button3_.invalidate();
button3_.setBackgroundResource(R.drawable.chickenclicked);
button3_.refreshDrawableState();
handler.postDelayed(new Runnable() {
public void run() {
button3_.invalidate();
button3_.setBackgroundResource(R.drawable.chicken);
button3_.refreshDrawableState();}}, 1000);
}
if( array_values == 4) {
button4_.invalidate();
button4_.setBackgroundResource(R.drawable.cowclicked);
button4_.refreshDrawableState();
handler.postDelayed(new Runnable(){
public void run(){
button4_.invalidate();
button4_.setBackgroundResource(R.drawable.cow);
button4_.refreshDrawableState();}}, 1000);
}
}
It's because you are creating handlers very fast and then they are all starting at the same time. You should look into how Handler's work and about Asyncronous/Background tasks.
Now back to your problem, you are calling the a loop and it is creating handlers all in a row and they are being created very fast (nanoseconds). They will then all launch 1 second from that creation time because of your postDelayed() call. This is why everything is popping up at the same time! All of these delay posts are being executed at almost the same time on concurrent background threads.
Instead of a for(int i,...) loop you want to have a global int i, just add it to the top of the file.
At the end of any of Simon's turn you'll want, inside of the if, else if statement inside assign_background (at the end of the Runnables, then you'll want to call go().
This might cause problems because you are trying to access the main thread from all these background threads. so you might have to call the function runOnMainUIThread() as a quick hack when you call the go function.
All in all, you are going to have some problems until you understand Handlers, Background Processes, and Threads. Definitely great knowledge to learn about and Android has solid documentation on it just FYI.
I have called a method in ServletContextListener as thread ..Now as per my need i have to delay the thread for 1 minutes and then start executing the method called in the thread but i am not able to do that as i am very new in this...
Here is my code ...
public class Startup implements ServletContextListener {
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
public void contextInitialized(ServletContextEvent sce) {
// Do your startup work here
System.out.println("Started....");
//captureCDRProcess();
new Thread(new Runnable() {
#Override
public void run() {
captureCDRProcess();
}
}).start();
}
Please help me ..
Thanks in advance..
To do this properly, you need to use a ScheduledThreadPoolExecutor and use the function schedule like this:
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(new Runnable() {
#Override
public void run() {
captureCDRProcess();
}
}, 1, TimeUnit.MINUTES);
Thread.sleep is not the way to go, because it does not guarantee that it wakes up after a minute. Depending on the OS and the background tasks, it could be 60 seconds, 62 seconds or 3 hours, while the scheduler above actually uses the correct OS implementation for scheduling and is therefore much more accurate.
In addition this scheduler allows several other flexible ways to schedule tasks like at a fixed rate or fixed delay.
Edit: Same solution using the new Java8 Lamda syntax:
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(() -> captureCDRProcess(), 1, TimeUnit.MINUTES);
Or you can delay creating the thread with Timer and TimerTask:
public void contextInitialized() {
// Do your startup work here
System.out.println("Started....");
Timer timer = new Timer();
TimerTask delayedThreadStartTask = new TimerTask() {
#Override
public void run() {
//captureCDRProcess();
//moved to TimerTask
new Thread(new Runnable() {
#Override
public void run() {
captureCDRProcess();
}
}).start();
}
};
timer.schedule(delayedThreadStartTask, 60 * 1000); //1 minute
}
Have a look at Thread.sleep(). Maybe add it to the new thread's run method, so that it sleeps the needed time before doing any meaningful work.
You can start thread and inside the thread use sleep method for one minute.
ScheduledThreadPoolExecutor has this ability, but it's quite heavyweight.
Here's a simple implementation with a test (signature close to Android's Handler.postDelayed()):
public class JavaUtil {
public static void postDelayed(final Runnable runnable, final long delayMillis) {
final long requested = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
long leftToSleep = requested + delayMillis - System.currentTimeMillis();
if (leftToSleep > 0) {
Thread.sleep(leftToSleep);
}
break;
} catch (InterruptedException ignored) {
}
}
runnable.run();
}
}).start();
}
}
Test:
#Test
public void testRunsOnlyOnce() throws InterruptedException {
long delay = 100;
int num = 0;
final AtomicInteger numAtomic = new AtomicInteger(num);
JavaUtil.postDelayed(new Runnable() {
#Override
public void run() {
numAtomic.incrementAndGet();
}
}, delay);
Assert.assertEquals(num, numAtomic.get());
Thread.sleep(delay + 10);
Assert.assertEquals(num + 1, numAtomic.get());
Thread.sleep(delay * 2);
Assert.assertEquals(num + 1, numAtomic.get());
}
I created a handler, to imitate timer task.
because TimerTask was acting differently on different tablets.
so I created this handler method.
in timer there was a method timerTask.cancel();
but how to stop this handler
it keeps on running even after the application is exited.
as you can see logs running even after back press.
Handler handler = new Handler();
public void recursivelycallHandler(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
recursivelycallHandler();
}
}, 100);
}
There are 3 methods to do that ..
handler.removeCallbacks(Runnable r);
handler.removeCallbacksAndMessages(null);
handler.removeMessages(int what)
In your case first two seem feasible .. add any of the above method in ondestroy or on a listener to backpress..
By putting any condition
Handler handler = new Handler();
int i = 0;
Runnable myRunnable = new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
if(i>5)
handler.removeCallback(myRunnable);
else{
i++;
handler.postDelayed(myRunnable, 100); // here is self calling
}
}
};
}
handler.postDelayed(myRunnable, 100);
Its recursive method but you can call the same Runnable object in run() instead of recursive method and remove that object when based on specific situation/condition
You can store flag (boolean var) to detect if you need to call for your handler and before exit app change this flag to false and stop calling handler.
you can do something like this below:
public void recursivelycallHandler(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
if(YOUR_CONDITION){
recursivelycallHandler();
}
}
}, 100);
}
Hope you got my point.
feel free to comment.
just add isFinished to your run method:
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isFinished())
return;
Log.d("handler is running", "true" + System.currentTimeMillis());
recursivelycallHandler();
}
}, 100);