I'm new to android and pretty new to the concept of timing in Java also. I've tried to create a simple app that counts the number of user clicks on the screen in five seconds. After the time ends, I want to disable the button and restart everything when clicking the 'Restart' button.
This is the current code:
public void clickCounter(View view){
++counter;
if(showCounter!=null)
showCounter.setText(Integer.toString(counter));
}
public void clickTimer(final View view) {
final Button Tap = findViewById(R.id.Tap);
clickCounter(view);
new CountDownTimer(5000, 5000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Tap.setEnabled(false);
}
}.start();
}
public void restartCounter(View view) {
counter=0;
showCounter.setText("Tap");
final Button Tap = findViewById(R.id.Tap);
Tap.setEnabled(true);
}
The button does disable after 5 seconds, but the restart button sometimes enables and then disables it right away (the counter and text changes properly).
I think the problem might be the way I'm using the Timer to do it (maybe I should use threads?)
You are creating a new timer on every button tap. So, when you reenable the button, one of your timers could be expiring, disabling the button afterwards. You should only create a new timer if there is none running.
To expand on Tiago Loureino's awesome answer, the problem is that you are creating a new CountDownTimer object every time the clickTimer() method is called.
The button does disable after 5 seconds, but the restart button sometimes enables and then disables it right away (the counter and text changes properly).
This 👆🏽 happens because you have several CountDownTimers executing their onFinish() method.
The solution to this problem is to have one single instance of your CountDownTimer. To put that in code, you can declare your CountDownTimer as below:
public CountDownTimer cdt = new CountDownTimer(5000, 5000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Tap.setEnabled(false);
}
};
You can then call cdt.start() anytime you want to start your the timer.
Related
I have this code in android studio:
The question is that if I give the button back and the main activity takes me, that is going to continue executing.
How do I make it so that once it's behind, it does not run what's in the onfinished?
new CountDownTimer (40000,1000) {
#Override
public void onTick(long l)
{
crono.setText("00:"+l/1000);
if(contador==10)
{
}
}
#Override
public void onFinish()
{
if(value.equals("tiempo"))
{
crono.setText("00:00");
}
else
{
esperar();
}
}
}.start();
CountDownTimer class help us to implement timer with custom time interval and duration. It provide 2 callback onTick(int millisUntilFinished) which called after each interval and onFinish is called when time duration is completed.
If you want to stop countdown then store instance countdown and call countdown.cancel() in onDestroy or button click(any where by user action)
You can refer this
The purpose of the service is to keep track of time since a button was pressed. If the menuactivity is showing, it updates some values on the menuactivity every minute using a timer, otherwise, it just updates itself.
It seems to work fine when the application is open or closed, but when the phone is off it slows down to less than half of what it should be (only showing like 10 minutes have passed after 21 real minutes have passed).
int startTime; //time at which the button is pressed
int time; //the current time, relative to startTime
#Override
public int onStartCommand(Intent intent, int flags, int startId){
startTime = (int)(System.nanoTime()/1000000000.0);
UpdateTimeTask updateTimeTask = new UpdateTimeTask();
timer = new Timer();
timer.schedule(updateTimeTask, 0, UPDATE_PERIOD); //update period is 60,000 (60 seconds)
return START_STICKY;
}
public class UpdateTimeTask extends TimerTask {
public void run() {
updateMenu();
}
}
public void updateMenu(){
time = (int) Math.round((System.nanoTime() / 1000000000.0) - startTime);
if(serviceCallbacks != null){ //it wont be null if its on menuactivity
serviceCallbacks.updateTimeElapsed(time/3600, time/60 - (time/3600) * 60);
}
}
If I have my phone off for a while and then go back in to menuactivity, it doesn't "fix itself" after a few cycles. I thought onStartCommand might be called more than once, but the only time the service can possibly be started is when the button is pressed.
but the only time the service can possibly be started is when the
button is pressed
That is not true. When your app go into the background (is no longer visible) it becomes a candidate to be killed if the system needs memory for other higher ranked apps. Also, the user can kill your app by swiping it from the task list. Because the service returns START_STICKY from onStartCommand(), the system will restart the service after some period of time, calling onStartCommand() with a null intent. This behavior makes a service unsuitable as the home for a data item you want to retain, such as startTime.
An alternative is to persist the value in SharedPreferences. A service is not needed and the periodic update processing can be done in your activity using the postDelayed() method of any view.
This sample activity outlines the basic logic:
public class ButtonActivity extends Activity {
private static final String TIME_KEY = "time";
private static final long PERIOD = 60*1000; // 60 seconds
private SharedPreferences mPrefs;
private Button mButton;
private TextView mTimeView;
private Runnable mDisplayTask = new Runnable() {
#Override
public void run() {
// show the time elapsed since button press in milliseconds
long elapsed = System.currentTimeMillis() - mPrefs.getLong(TIME_KEY, 0);
mTimeView.setText(""+elapsed);
// schedule next display update
mTimeView.postDelayed(mDisplayTask, PERIOD);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPrefs = getPreferences(MODE_PRIVATE);
// clear the button press time
setPressTime(0);
setContentView(R.layout.activity_demo);
mButton = (Button)findViewById(R.id.button);
mTimeView = (TextView)findViewById(R.id.time);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// save the button press time
setPressTime(System.currentTimeMillis());
// start the display updates
mDisplayTask.run();
}
});
}
#Override
protected void onPause() {
super.onPause();
// activity no longer visible; stop the updates
mTimeView.removeCallbacks(mDisplayTask);
}
#Override
protected void onResume() {
super.onResume();
// activity is visible
// if the button has been pressed, start the display updates
if (mPrefs.getLong(TIME_KEY, 0) > 0) {
mDisplayTask.run();
}
}
private void setPressTime(long time) {
// persist the button press time
SharedPreferences.Editor ed = mPrefs.edit();
ed.putLong(TIME_KEY, time);
ed.commit();
}
}
The accepted answer is correct, but only solved part of the problem. The other problem was that I was using System.nanoTime() instead of .currentTimeMillis(); .nanoTime() stops when the screen is off. Putting this here for possible future googlers.
I am trying to make simple maths game. Aim of the game is to answer so many questions right in a certain time limit.
I have a timer which counts down and calls my final screen to set your highscore. Problem is, when testing the app if the back button is pressed before timer is done, it seems to continue in the background and my highScore screen randomly appears. How can I make this stop?
Here is the code for my timer:
/**
* timer method
*/
public void timer() {
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Intent i = new Intent(MainActivity.this, HighScoreScreen.class);
i.putExtra("Score", score);
startActivity(i);
resetScore();
finish();
}
}.start();
}
One solution to this very particular problem would be to override onBackPressed and cancel your timer there. On the other hand, if you want to cancel the timer when there is any interruption (e.g. user receives a call while using your app), you could perhaps place the cancel call in a lifecycle method like onStop.
I recently began working with Java and am exploring Android development. I was trying to port over one of the Java programs I made, but I am having some difficulty with getting the java Timer to function the same way in Android. I read through a number of posts and they, for the most part, indicated that it would be better to use the Handler class in android as opposed to Timer.
This was my timer in Java:
playTimer = new Timer(1000/model.getFPS(), new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// do something
...
if( finished everything ) playTimer.stop();
}
});
And once a certain button was clicked, I would simply run "playTimer.start()" to start it.
As you can see, I had it set up so that the user could set the FPS they wanted (by simply setting the first parameter of the Timer class to 1000/model.getFPS()).
Now I've tried to do something similar in Android using handlers, but I am having some difficulty. It appears that the Handler ticks are not firing at the proper intervals. It seems that they are quite slow compared to what I need it to be. This is what I did in android so far:
public void startTimer() {
playHandler = new Handler();
startTime = System.currentTimeMillis();
playHandler.removeCallbacks(updateTimeTask);
playHandler.postDelayed(updateTimeTask, 0);
}
private Runnable updateTimeTask = new Runnable() {
public void run() {
// do something
...
if( finished everything ) playHander.cancel();
else {
playHandler.postDelayed(updateTimeTask, 1000/model.getFPS());
}
}
};
Excuse the semi-pseudocode. Can anyone shed any light? Thanks guys.
You can use a timer as below. The timer runs every second incrementing the counter. Displs the counter value in textview.
Timer runs on a different thread. SO you should set the text on the UI Thread.
The counter runs from 0 to 99. After 99 the timer is cancelled. Also cancel the timer when not required like in onPause().
public class MainActivity extends Activity {
TextView _tv,tv2;
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(R.string.app_name);
_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 ); //change this value of 1000 to whatever you need.
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
_t.cancel();
}
}
If you decide not to use Timer (for whatever reason) you can just write a separate Thread that sleeps for x milliseconds and then wakes up and calls whatever Runnable you want it to call. That's going to be pretty precise. I have it working at the 10 millisecond level and it works quite nicely.
Just remember that it HAS to call a Runnable because a separate Thread can't have direct effect on anything on the main display thread.
public boolean keepPlayingAnimation = true
Handler h = new Handler()
Runnable updateDisplay = new Runnable(){
public void run(){
//do something in my display;
}
}
new Thread(){
public void run(){
while(keepPlayingAnimation){
try{
sleep(10);
}catch(Exception e){
}
h.post(updateDisplay);
}
}
}.start();
Just don't forget to set keepPlayingAnimation to false when you're done with this cause otherwise it will sit there running in the background for ever (or just about).
Take a look at Android Timer
It already has everything you need i guess. From ticking every 1 second to finish handly and so on.
Here is an example how to setup an TimerTask: setup
Not sure if you need such but i just remembered that i made this.
There is a listener code.
Method onCreate:
rssListView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
//Then it stops
rssListView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
);
I want to run it again, when the button clicked:
b1.setOnClickListener(
new View.OnClickListener() {
// #Override
public void onClick(View v) {
// ...
}
}
);
Tell me how I can activate the listener on the button?
I think you talking about Pull-to-Refresh functionality. If yes - look at this article.
What is it you want to run again.
If you want the function to be called on button click then do the function call in the onClick method of the listener. Once a listener is added to a UI Widget it keeps on listening to any UI Events on that object till the application is running.