Before I start I have looked at lots of threads including:
How to add time to countdown timer?
Android game countdown timer
But I just cant get my timer to work in the way I require. I want the timer to be counting down from say 30 and when and image is pressed (named imageview1 in this case) the timer adds 3 seconds to the timer to give it more time. I know you cannot essentially add the time while its running and you need to cancel and then start a new timer, The code I have so far is :
public void onClick(View v) {
// TODO Auto-generated method stub
//GlobalClass global = new GlobalClass();
Random rand = new Random();
CountDownTimer thetimer = new myTimer(millisInFuture, 1000);
switch(v.getId()) {
case R.id.buttonstart:
btnstart.setVisibility(View.INVISIBLE);
thetimer.start();
break;
case R.id.imageView1:
if (thetimer != null){
thetimer.cancel();
thetimer = new myTimer(countdownPeriod + 3000, 1000).start();
}
break;
with lots of other case references then :
public class myTimer extends CountDownTimer {
public myTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
timedisplay.setText("Time Left: " + millisUntilFinished / 1000);
countdownPeriod=millisUntilFinished;
}
#Override
public void onFinish() {
timedisplay.setText("Timer Finished");
started = false;
btnstart.setVisibility(View.VISIBLE);
}
}
I think the problem is its not cancelling the original timer so the label that shows the timer does some crazy things, like jumping around on different numbers both up and down as there would appear more than 1 class of thetimer. That is even though I have included the line thetimer.cancel(); The timer works fine if I just let it run to 0.
Any help would be great
You should not create your timer as a local in onClick. Instead create it as a global and start it somewhere else (in onCreate perhaps).
What happens with your current code is that whenever onClick is called a new timer is created and you then cancel the new timer - which has no effect on any previously created timer(s).
Try something like this:
public class MyActivity extends Activity {
CountDownTimer thetimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
thetimer = new myTimer(millisInFuture, 1000);
}
public void onClick(View v) {
Random rand = new Random();
switch(v.getId()) {
case R.id.buttonstart:
btnstart.setVisibility(View.INVISIBLE);
thetimer.start();
break;
case R.id.imageView1:
if (thetimer != null) {
thetimer.cancel();
thetimer = new myTimer(countdownPeriod + 3000, 1000).start();
}
break;
}
}
}
You will still have to keep track of the global time somewhere - i.e. the countDonwPeriod used to re-create the timer instance when an image is touched - it should probably be extracted from the timer before canceling it.
Related
I need that a button can run automatically every 1-2 seconds, and, when the if condition (that i have in the method which is used by the button) is fulfilled, this function must be stopped.
I've tried this but it wasn't what i wanted because with this code the button only runs one time:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Consulta.performClick();
}
}, 1000);
onClick of my button:
public void consultaBD(View view)
{
DB db = new DB(getApplicationContext(),null,null,1);
String buscar = text_view.getText().toString();
String[] datos;
datos=db.buscar_reg(buscar.trim());
db.infraccion(buscar.trim());
if(datos[2] =="Encontrado")
{
App.matricula=buscar;
startActivity(new Intent(getApplicationContext(), MatriculasActivity.class));
Toast.makeText(getApplicationContext(),datos[2],Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),datos[2],Toast.LENGTH_SHORT).show();
}
}
Another method would be to use Timers to initiate the button click every x seconds. However, in this answer I'll stick with the method you're using. Your handler appears to be incorrect, try something like this instead:
Replace your handler with:
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
Consulta.performClick();
handler.postDelayed(this, 1000);
}
};
And initiate it with: (where 1000 is the time (in milliseconds) between each execution)
handler.postDelayed(runnable, 1000);
UPDATE:
You have also requested that the event is fired when the text inside of a textbox is changed. To do this, you need to create a new event listener (make sure you replace field1 with the actual reference to your textbox):
field1.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
/* Add the Handler Call here */
handler.postDelayed(runnable, 1000);
}
});
whatever context I understood, here is the raw code which may help you.
Handler handler = new Handler();
//initialize this method once by either clicking on button or as the activity starts
void checkAndPerformClick(boolean conditionFulfilled) {
if (conditionFulfilled) {
handler.removeCallbacksAndMessages(null);
return;
}
handler.postDelayed(new Runnable() {
#Override
public void run() {
Consulta.performClick();
checkAndPerformClick(datosEqualsEncontrado());
}
}, 1000);
}
boolean datosEqualsEncontrado() {
// apply your logic here as the name suggests
return false;
}
I have developed an android application which extracts single line text messages from the server. Once a button is clicked, it makes a function call which gets the next message from the server. Some of those messages are time based,
i.e those messages have to be displayed in the TextView for a particular amount of time and after that time is elapsed, it should automatically make the function call to get the next message from the server(i.e without the button being clicked).
Could someone please help me out in achieving this.
I tried using while loop as follows:
while(!presentTime.equals(expiryTime)){
calculatePresentTym(); //This method calculates the presentTime value
display.settext(the received instruction);
}
if(presentTime.equals(expiryTime))
(make the function call)
If I do this, nothing is being displayed till presentTime and expiryTime are equal. Once they are equal, the next instruction is automatically fetched by the function call and is displayed in the TextView.
Use a a handler
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
#Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
T0 cancel the run
m_handler.removeCallbacks(m_handlerTask); // to cancel the run
You can also use a timer but you will have to use runOnUiThread to update ui since timer runs on a different thread.
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
//do something
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
//update ui
}
});
}
}, 1000, 1000 );
Note:
gets the next message from the server
Getting the message from server should be done on a background thread.
Edit:
While copy pasting the initialization part was missing. You have a counter i that is displayed in the textview. The counter increases by 1 every second. When it reaches 100 you cancel the run. Modify the below according to your requirements.
public class MainActivity extends Activity {
TextView tv;
Handler m_handler;
Runnable m_handlerTask ;
int i=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
m_handler = new Handler();
m_handlerTask = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if(i<=100)
{
tv.setText(""+i);
i++;
}
else
{
m_handler.removeCallbacks(m_handlerTask);
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
}
}
Use a timer. Schedule the timer for repeated interval executions, and after each execution you can get the next text from the server and display the same.
Check the Timer reference scheduleAtFixedRate(TimerTask task, long delay, long period)
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.
For a side project of mine, I'm devoloping an android app with java. I don't know java a lot but i'm trying ^^.
The project is to have an Alarm at a random time in a certain range. The problem is that my chronometer and button freeze, but everything still works! Does anyone has maybe another solution for the thread.sleep ??
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void StartChrono(View view) {
final Chronometer chrono = (Chronometer)findViewById(R.id.chronometer1);
chrono.setBase(SystemClock.elapsedRealtime());
chrono.start();
//Tick();
}
public int RandomTime(int min, int max)
{
int random = max - min;
Random rand= new Random();
random = rand.nextInt(random)+min;
return random;
}
public boolean CheckUp(int randomtime,int chronotime)
{
boolean check = false;
if(randomtime== chronotime)
{
check = true;
}
return check;
}
public void Tick()
{
boolean check = false;
int randomtime = RandomTime(20,150);
int time=1;
do
{
check = CheckUp(randomtime,time);
time = time +1;
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Error - 000");
alertDialog.setMessage("Could not check!");
alertDialog.show();
}
}while(check == false);
if(check == true)
{
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Yuy");
alertDialog.setMessage("Switch!");
alertDialog.show();
}
}
}
I wouldn't use Thread.sleep(), I would use a Timer.
You can set a time and the Timer automatically calls the associated task.
In Android it would work something like this:
http://android.okhelp.cz/timer-simple-timertask-java-android-example/
I used it once myself, but that is some time ago.
Btw.:
You don't have to write a method to check for a boolean value.
This also works:
boolean check = 5>3;
System.out.println("check: " + check);//"check true"
I'd definately use a Handler for this task: http://developer.android.com/reference/android/os/Handler.html
A basic example would be this:
long timeDelay = 1000; // Set this to your random number.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do whatever you need to do after a specified interval.
}
}, timeDelay);
Instantiate the Handler inside your onCreate and keep the reference around so you can call it inside your method.
Just to clarify, why you can't use Thread.sleep() for "sleeping" a specific amount of time, is this: when you call Thread.sleep() you call it on the UI thread, so every component running on the UI thread (buttons, textfields and so on) will "sleep" for the given amount of time and hence you basically halt the whole application.
Also see the documentation for Thread.sleep:
Causes the thread which sent this message to sleep for the given
interval of time (given in milliseconds).
I'm trying to make a countdown timer in android for use in a small android app. The app will countdown from some number of seconds to 0, upon which it will do some action. I'm using the coundowntimer supplied by android.os.countdowntimer. Here is my code:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.quizlayout);
new CountDownTimer(30000, 1000) {
TextView tx = (TextView) findViewById(R.id.textView2);
public void onTick(long millisUntilFinished) {
tx.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
tx.setText("done!");
}
}.start();
}
However, this countdown timer is really slow. It takes like 3 real-time seconds for the timer to countdown by one second. I wonder what's going on? The code I have above is more or less copied straight from google (CountDownTimer)
Can anyone help me as per why my timer is so slow, and offer a way to speed it up a bit?
(EDIT): I am running this on an emulator, the intel atom x86. I am emulating an android 2.3.3 environment.
According to Android documentation for countdown timer
The calls to onTick(long) are synchronized to this object so that one call to onTick(long) won't ever occur before the previous callback is complete. This is only relevant when the implementation of onTick(long) takes an amount of time to execute that is significant compared to the countdown interval.
Take a look at this example for countdown timer
Countdown timer example
Alternately you can spawn a new thread and just get that thread to sleep for the interval you want and take actions when it wakes or vice versa.
You can also timertask
use a handler that will post the same runnable . this will remove the need for extra threads :
Handler handler=new Handler();
handler.postRunnable(... , 1000) ;
in the runnable , call the postRunnable again for the same handler (and add a condition for when to stop) .
CountDownTimer is not efficient regardless to ui updating performances. For a flawless ui update, it is better to create a custom countdown. I did my own so here it is. It is flawless on my app.
public abstract class CountDown {
int totalTime = 0;
int tickTime = 0;
Thread thread;
boolean canceled = false;
public CountDown(int totalTime,int tickTime){
this.totalTime = totalTime;
this.tickTime = tickTime;
}
public abstract void onTick();
public abstract void onFinish();
public void start(){
thread = new Thread(new Runnable() {
#Override
public void run() {
// Do in thread
canceled = false;
for (int elapsedTime = 0; elapsedTime < totalTime; elapsedTime += tickTime) {
if(!canceled){
onTick();
try {
thread.sleep(tickTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
if(!canceled){
onFinish();
}
}
});
thread.start();
}
public void cancel(){
canceled = true;
}
}
Remember that every time you have to update your ui, call a runOnUiThread, or else you will have an exception, you are not in a handler and not on ui thread.
Here is how to use it in your code, it is identical to CountDownTimer, so you could just rename lines in your code :
CountDown cDown = new CountDown(10000, 20) {
public void onTick() {
// Do something
}
public void onFinish() {
runOnUiThread(new Runnable() {
#Override
public void run() {
myButton.setImageDrawable(drawable);
}
});
}
};