I'm having an issue with my CountDownTimer. Here's the situation:
Working on a game and I am not using a framework (who needs one, right? coughs) and I have a CountDownTimer running. This CountDownTimer is used to calculate how long a player has to complete a level, and also update the screen per 100ms tick.
In the first level this works fine, but in the second level it ticks per 50ms, and in the third per 60/90/50ms ticks (yes, in that order repeatedly) making the game behave odly and messing up collision.
I have no idea what's going on here.
I've ruled out if it's dependant on the level by loading later levels first, and upon solving those the problem arrises all the same.
I have, however, pinpointed where it's going wrong: During the loading for a new level, and only then; even reloading a current level doesn't bring this bug up.
I have a suspicion that somehwere in this code, something's not going as it should be:
public void prepareNewLevel(){
RelativeLayout rl = (RelativeLayout)findViewById(R.id.game);
level.clear();
movables.clear();
img_move.clear();
img_noMove.clear();
timerCount.cancel();
totalSolved = 0;
solvable = 0;
levelWidth = 0;
levelHeight = 0;
allCollided = false;
firstDraw = true;
rl.removeAllViewsInLayout();
}
level, movables, img_move and img_noMove are List items.
This my timer:
MyCount update = new MyCount(15*1000, 100);
This is MyCount:
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
remaining_time = millisUntilFinished;
if(!loadingNewLevel)
MoveObjects();
}
#Override
public void onFinish() {
resetLevel = true;
upMotion = false;
downMotion = false;
leftMotion = false;
rightMotion = false;
update.start();
}
}
And then I also call update.start() at the end of my loadLevel() function. I first thought I had two timers running at once, but writing to the LogCat showed me that was false, concidering I got a neat 'reset' message every 15 seconds, instead of at multiple moments smaller than 15s.
And that's basically the issue here. Now that I know where it's being caused and what the issue is, how do I solve it?
-Zubaja
Try use Timer instead CountDownTimer:
// start timer inside your method
if( timer != null) timer.cancel();
timer = new Timer();
timer.scheduleAtFixedRate( new TimerTask()
{
#Override
public void run()
{
handler.obtainMessage( yourInegerMessage).sendToTarget();
}
}, 100, 15000);
// and define you handler
public Handler handler = new Handler( new Handler.Callback()
{
#Override
public boolean handleMessage( Message message)
{
// use 'message.what' as yourInegerMessage
// ...
return true;
}
});
// and stop your timer after first time
May be this help you.
May be you start more one CountDownTimer? Try stop existing CountDownTimer before start new CountDownTimer.
Related
I want to make an application about mini game.
Detail : In 2 seconds you must to answer a question if you don't answer or the answer is wrong -> Game Over . But if your answer is true the Timer will reset become 0 and countdown again with diffirent question.
I have already seen many code about timer in website but I don't understand clearly about it :(
So I want to ask : How can i set up a timer run only 2 seconds and how can i reset it and continue with a new question ?
Please help me.
you can use CountDownTimer in android like this:
public class Myclass {
myTimer timer =new myTimer(2000,1000);
public void creatQuestion(){
timer.start();
//method you init question and show it to user
}
public void getUserAnswer(/*evry thing you expected*/)
{
//if answer is true call timer.start()
//else call timer.onFinish(); to run onfinish in timer
}
public class myTimer extends CountDownTimer {
public myTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
// you can update ui here
}
#Override
public void onFinish() {
this.cancel();
//fire game over event
}
}
}
i hope it make you satisfy
I've done something similar using Thread/Runnable.
Thread t = new Thread(new Runnable() {
public void run() {
final long startTime = getTime();
final long maxEndTime = startTime + 2000L;
try {
while (shouldContinueWaiting()) {
if (getTime() > maxEndTime) {
throw new TimeoutException();
}
sleep();
}
} catch (InterruptedException e) {
handleInterrupt();
} catch (TimeoutException e) {
handleTimeout();
}
}
boolean shouldContinueWaiting() {
// Has the user already answered?
}
void handleInterrupt() {
// The user has answered. Dispose of this thread.
}
void handleTimeout() {
// User didn't answer in time
}
void sleep() throws InterruptedException {
Thread.sleep(SLEEP_DURATION_IN_MILLIS);
}
void getTime() {
return System.currentTimeMillis();
}
then you can start/restart the thread by:
t = new Thread(same as above...);
t.start();
and stop by:
t.interrupt();
We want to use the Timer class.
private Timer timer;
When you're ready for the timer to start counting -- let's say it's after you press a certain button -- do this to start it:
timer = new Timer();
timer.scheduleAtFixedRate(incrementTime(), 0, 100);
The first line is us creating a new Timer. Pretty standard. The second line, however, is the one I wanted you to see.
incrementTime() is a method that is called at the end of every "tick" of the clock. This method can be called whatever you want, but it has to return an instance of TimerTask. You could even make an anonymous interface if you want, but I prefer moving it off into its own section of code.
The 0 is our starting location. We start counting from here. Simple.
The 100 is how large a "tick" of the clock is (in milliseconds). Here, it's every 100 milliseconds, or every 1/10 of a second. I used this value at the time of writing this code because I was making a stopwatch application and I wanted my clock to change every 0.1 seconds.
As for your project, I'd suggest making the timer's task be your question switch method. Make it happen every 2000 milliseconds, or 2 seconds.
You can use a Handler.
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//this will happen after 2000 ms
}
}, 2000);
Maybe this can help you:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
// FIRE GAME OVER
handler.postDelayed(this, 2000); // set time here to refresh textView
}
});
You can fire your game over after 2000 milliseconds.
If you get the question correct -> remove callback from handler and reset it when the next question starts.
I am trying to develop a game like matching small pictures.My problem is that i want to finish the game after a time period.For instance in level 1 we have 10 seconds to match picture.I want to display remaining time also.I will be thankful for any help.
Since you also want to show the countdown, I would recommend a CountDownTimer. This has methods to take action at each "tick" which can be an interval you set in the constructor. And it's methods run on the UI Thread so you can easily update a TextView, etc...
In it's onFinish() method you can call finish() for your Activity or do any other appropriate action.
See this answer for an example
Edit with more clear example
Here I have an inner-class which extends CountDownTimer
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.some_xml);
// initialize Views, Animation, etc...
// Initialize the CountDownClass
timer = new MyCountDown(11000, 1000);
}
// inner class
private class MyCountDown extends CountDownTimer
{
public MyCountDown(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
frameAnimation.start();
start();
}
#Override
public void onFinish() {
secs = 10;
// I have an Intent you might not need one
startActivity(intent);
YourActivity.this.finish();
}
#Override
public void onTick(long duration) {
cd.setText(String.valueOf(secs));
secs = secs - 1;
}
}
#nKn described it pretty well.
However, if you do not want to mess around with Handler. You always can delay the progress of the system code by writing:
Thread.sleep(time_at_mili_seconds);
You probably need to surround it with try-catch, which you can easily add via Source-> Surround with --> Try & catch.
You can use postDelayed() method of Handler...pass a Thread and specific time after which time the Thread will be executed as below...
private Handler mTimerHandler = new Handler();
private Runnable mTimerExecutor = new Runnable() {
#Override
public void run() {
//here, write your code
}
};
Then call postDelayed() method of Handler to execute after your specified time as below...
mTimerHandler.postDelayed(mTimerExecutor, 10000);
In Java for Android, I want to create a variable that increases by 1 every second, in other words, it counts, that way I can check to see if a function has been called in the past 3 seconds, and if not, I want it to do something different than if it had been.
Is there any built-in way to do this? I'm familiar with the Timer class, but it doesn't seem to work the way I would want it to.. is there anything else?
tl;dr: I want to create a variable that increases by 1 every second, so I can use it to treat a function differently based on how long it has been since its last call. Is there an easy way to do this? If not, what is the hard way to do this?
Why not store the last time the method was called instead, then check it against the current time?
private long timeLastCalled;
public void someMethod() {
timeLastCalled = SystemClock.elapsedRealTime();
}
public boolean someMethodCalledRecently() {
return (SystemClock.elapsedRealTime() - timeLastCalled) > 3000;
}
final int[] yourVariable = new int[1];
yourVariable[0] = 0;
updateVariableTimer = new CountDownTimer(howLongYouWantTimerToLast, 1000) {
#Override
public void onTick(long l) {
yourVariable[0] += 1;
}
}.start();
Or Alternatively to do it with a flag instead of keeping track of variable counting:
final boolean functionCalledRecently = false;
hasFunctionBeenCalledRecentlyTimer = new CountDownTimer(3000, 1000) {
#Override
public void onTick(long l) {
functionCalledRecently = true;
}
#Override
public void onFinish() {
functionCalledRecently = false;
}
}.start();
If you just need to see if the method has been called within the last 3 seconds you can use a Handler and a Boolean flag to acomplish this.
private Handler mHandler = new Handler();
private boolean wasRun = false;
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if(wasRun){
//whatever you want to do if run
}
mHandler.postDelayed(this, 3000);
}
},3000); //3 sec
In this example the Handler will run on a 3 second delay. Each time it runs it will check to see if the other method was perviously called by evaluating if(wasRun). This way you can change what happens if the method was/was not called. The handler will then start iself again on another 3 second delay. All you have to do then is update the wasRun flag to be true if your method was called, or false if it was not. .
First of all, I could not even chose the method to use, i'm reading for hours now and someone says use 'Handlers', someone says use 'Timer'. Here's what I try to achieve:
At preferences, theres a setting(checkbox) which to enable / disable the repeating job. As that checkbox is checked, the timer should start to work and the thread should be executed every x seconds. As checkbox is unchecked, timer should stop.
Here's my code:
Checking whether if checkbox is checked or not, if checked 'refreshAllServers' void will be executed which does the job with timer.
boolean CheckboxPreference = prefs.getBoolean("checkboxPref", true);
if(CheckboxPreference == true) {
Main main = new Main();
main.refreshAllServers("start");
} else {
Main main = new Main();
main.refreshAllServers("stop");
}
The refreshAllServers void that does the timer job:
public void refreshAllServers(String start) {
if(start == "start") {
// Start the timer which will repeatingly execute the thread
} else {
// stop the timer
}
And here's how I execute my thread: (Works well without timer)
Thread myThread = new MyThread(-5);
myThread.start();
What I tried?
I tried any example I could see from Google (handlers, timer) none of them worked, I managed to start the timer once but stoping it did not work.
The simpliest & understandable code I saw in my research was this:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
5000
);
Just simply use below snippet
private final Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
//
// Do the stuff
//
handler.postDelayed(this, 1000);
}
};
runnable.run();
To stop it use
handler.removeCallbacks(runnable);
Should do the trick.
Use a CountDownTimer. The way it works is it will call a method on each tick of the timer, and another method when the timer ends. At which point you can restart if needed. Also I think you should probably be kicking off AsyncTask rather than threads. Please don't try to manage your own threads in Android. Try as below. Its runs like a clock.
CountDownTimer myCountdownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
// Kick off your AsyncTask here.
}
public void onFinish() {
mTextField.setText("done!");
// the 30 seconds is up now so do make any checks you need here.
}
}.start();
I would think to use AlarmManager http://developer.android.com/reference/android/app/AlarmManager.html
If checkbox is on call method where
AlarmManager alarmManager = (AlarmManager)SecureDocApplication.getContext()
.getSystemService(Context.ALARM_SERVICE);
PendingIntent myService = PendingIntent.getService(context, 0,
new Intent(context, MyService.class), 0);
long triggerAtTime = 1000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 5000 /* 5 sec*/,
myService);
If checkbox is off cancel alarm manager
alarmManager.cancel(myService);
"[ScheduledThreadPoolExecutor] class is preferable to Timer when multiple worker threads are needed, or when the additional flexibility or capabilities of ThreadPoolExecutor (which this class extends) are required."
per...
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
It's not much more than the handler, but has the option of running exactly every so often (vice a delay after each computation completion).
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
...
final int THREAD_POOL_SIZE = 10;
final int START_DELAY = 0;
final int TIME_PERIOD = 5;
final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
ScheduledThreadPoolExecutor pool;
Runnable myPeriodicThread = new Runnable() {
#Override
public void run() {
refreshAllServers();
}
};
public void startTimer(){
pool.scheduleAtFixedRate(myPeriodicThread,
START_DELAY,
TIME_PERIOD,
TIME_UNIT);
}
public void stopTimer(){
pool.shutdownNow();
}
Thanks to everyone, I fixed this issue with using Timer.
timer = new Timer();
timer.scheduleAtFixedRate(
new java.util.TimerTask() {
#Override
public void run() {
for (int i = 0; i < server_amount; i++) {
servers[i] = "Updating...";
handler.sendEmptyMessage(0);
new MyThread(i).start();
}
}
},
2000, 5000);
I've made a simple Android music player. I want to have a TextView that shows the current time in the song in minutes:seconds format. So the first thing I tried was to make the activity Runnable and put this in run():
int position = 0;
while (MPService.getMP() != null && position<MPService.duration) {
try {
Thread.sleep(1000);
position = MPService.getSongPosition();
} catch (InterruptedException e) {
return;
}
// ... convert position to formatted minutes:seconds string ...
currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);
But that fails because I can only touch a TextView in the thread where it was created. So then I tried using runOnUiThread(), but that doesn't work because then Thread.sleep(1000) is called repeatedly on the main thread, so the activity just hangs at a blank screen. So any ideas how I can solve this?
new code:
private int startTime = 0;
private Handler timeHandler = new Handler();
private Runnable updateTime = new Runnable() {
public void run() {
final int start = startTime;
int millis = appService.getSongPosition() - start;
int seconds = (int) ((millis / 1000) % 60);
int minutes = (int) ((millis / 1000) / 60);
Log.d("seconds",Integer.toString(seconds)); // no problem here
if (seconds < 10) {
// this is hit, yet the text never changes from the original value of 0:00
currentTime.setText(String.format("%d:0%d",minutes,seconds));
} else {
currentTime.setText(String.format("%d:%d",minutes,seconds));
}
timeHandler.postAtTime(this,(((minutes*60)+seconds+1)*1000));
}
};
private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder rawBinder) {
appService = ((MPService.LocalBinder)rawBinder).getService();
// start playing the song, etc.
if (startTime == 0) {
startTime = appService.getSongPosition();
timeHandler.removeCallbacks(updateTime);
timeHandler.postDelayed(updateTime,1000);
}
}
what about this:
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
//your code
}
}, delay, period);
Use a Timer for this (instead of a while loop with a Thread.Sleep in it). See this article for an example of how to use a timer to update a UI element periodically:
Updating the UI from a timer
Edit: updated way-back link, thanks to Arialdo: http://web.archive.org/web/20100126090836/http://developer.android.com/intl/zh-TW/resources/articles/timed-ui-updates.html
Edit 2: non way-back link, thanks to gatoatigrado: http://android-developers.blogspot.com/2007/11/stitch-in-time.html
You have to use a handler to handle the interaction with the GUI. Specifically a thread cannot touch ANYTHING on the main thread. You do something in a thread and if you NEED something to be changed in your main thread, then you call a handler and do it there.
Specifically it would look something like this:
Thread t = new Thread(new Runnable(){
... do stuff here
Handler.postMessage();
}
Then somewhere else in your code, you do
Handler h = new Handler(){
something something...
modify ui element here
}
Idea its like this, thread does something, notifies the handler, the handler then takes this message and does something like update a textview on the UI thread.
This is one more Timer example and I'm using this code in my project.
https://stackoverflow.com/a/18028882/1265456
I think the below blog article clearly gives a very nice solution. Especially, if you are a background service and want to regularly update your UI from this service using a timer-like functionality.
It really helped me, much more than the 2007 blog link posted by MusiGenesis above.
https://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from-a-background-service/