How to schedule a function every defined time with the option to change this time?
I found that I can do it using timer & timerTask or handler. The problem that it dosen't repeats the time I defined, it repeats randomaly...
runnable = new Runnable() {
#Override
public void run() {
//some action
handler.postDelayed(this, interval);
}
};
int hours = settings.getIntervalHours();
int minutes = settings.getIntervalMinutes();
long interval = (hours * 60 + minutes) * 60000;
changeTimerPeriod(interval);
private void changeTimerPeriod(long period) {
handler.removeCallbacks(runnable);
interval = period;
runnable.run();
}
Use a Handler object in the onCreate method. Its postDelayed method causes the Runnable parameter to be added to the message queue and to be run after the specified amount of time elapses (that is 0 in given example). Then this will queue itself after fixed rate of time (1000 millis in this example).
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
android.os.Handler customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable()
{
public void run()
{
//write here whaterver you want to repeat
customHandler.postDelayed(this, 1000);
}
};
I used the solution here
But in the code where the handler was initialized, I used
mHandler = new Handler(getMainLooper);
instead of
mHandler = new Handler();
which worked for me
Related
I am learning android. I made this stopwatch app work from my reference book.It only shows Hour:minutes:seconds but I want to add milliseconds right to the seconds.how do I do that.
code::-
public class StopWatchActivity extends AppCompatActivity {
int seconds;
boolean running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stop_watch);
runTimer();
}
public void startTimer(View view){
running = true;
}
public void stopTimer(View view){
running = false;
}
public void resetTimer(View view){
running = true;
seconds = 0;
}
public void runTimer(){
final TextView textView = (TextView) findViewById(R.id.timer);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
int sec = seconds % 60;
String time = String.format("%d:%02d:%02d", hours,
minutes,sec);
textView.setText(time);
if(running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
The first step would be to change the field seconds to milliSeconds because you want to keep track of that TimeUnit.
When restarting your handler with handler.postDelayed(this, 1000); define 1 millisecond as delay instead of 1000 (= 1 Second) like this handler.postDelayed(this, 1); then you just need to adjust your calculations and you are done :-)
An easier solution would be:
Instead of saving the elapsed seconds in your activity, save the time that the timer started (e.g. startTime)
Then, in your handler's runnable, get the current time and subtract the start time to find the elapsed time.
Pseudocode:
long startTimeNanos
public void runTimer() {
startTime = new Date()
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
long currentTime = System.nanoTime()
long elapsedNanos = currentTime - startTimeNanos
// calculate seconds and millis
// and set the textview text
handler.postDelayed(this, 1000);
}
});
}
This way, you can change the time that the handler fires and it won't affect anything else.
I have a problem with an handler that has to be executed every X seconds inside a Service. Basically the timing is not precise at all, some times the handler is called every X seconds, then nothing for 30 seconds and then many calls in a single second.
Handler handler = new Handler();
handler.postDelayed(runnable, 0);
private Runnable runnable = new Runnable() {
#Override
public void run() {
new postToCassandra().execute();
handler.postDelayed(this, CassandraPostBatch.TIME_INTERVAL);
}
};
It might be your asynchronous task causing the delay.
Just a note, your scheduling implementation looks a little strange. Maybe you should try something like this, could prove to be more effective.
private static final int TIMER_RATE = 30000;
private static final int TIMER_DELAY = 0;
private Timer timer;
private void startTimer() {
cancelTimer();
scheduleTimer();
}
private void scheduleTimer() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
new postToCassandra().execute();
}
}, TIMER_DELAY, TIMER_RATE);
}
private void cancelTimer() {
if (timer != null)
timer.cancel();
}
and then just call startTimer(). You could also implement a listener in your PostToCassandra task that will notify the TimerTask when it is done so that it can start with the next post.
I'm looking for a way to increment an integer every 30 seconds after a button is pressed. The problem I am having is that my code currently waits 30 seconds to increment the integer by 1 but then only one second for every integer after. this is my code.
int delay = 5000; // delay for 5 sec.
int period = 30000; // repeat every 30 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if(ammo_remaining<10){
update_ammo();``
}
}
});
}
}, delay, period);
Moving the recursive postdelayed call into your (ammo<10) if statement should give you the behavior you want.
int delay = 5000; // delay for 5 sec.
int period = 30000; // repeat every 30 sec.
int ammo_remaining = 10;
boolean reloading = false;
Handler handler=new Handler();
protected void shoot()
{
ammo_remaining--;
update_ammo();
if( ! reloading) //if not reloading
{
reloading = true;
handler.postDelayed(r, delay);
}
}
Runnable r=new Runnable()
{
public void run()
{
if(ammo_remaining<10)
{
ammo_remaining++;
update_ammo();
handler.postDelayed(r, period);
}
else{reloading=false;}
};
};
edit:
when shooting multiple times, you are creating many instance of the runnable through the handler, that all flood in after the first 30 seconds... you just need to create a boolean flag to keep track of the first request to reload
that 'reloading' flag and check should do the trick...
Button btn = (Button)findViewById(R.id.your button);
// first get your button;
final Handler hand = new Handler();
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
hand.post(new Runnable(){
#override public void run(){
(your int)++; // this will increase your int on step;
hand.postDelayed(this,30*1000); // this will do the same thing after 30 seconds again;
}
}
}
});
Try using handler:
int delay = 5000; // delay for 5 sec.
int period = 30000; // repeat every 30 sec.
Handler handler=new Handler();
protected void your_calling_method()
{
handler.postDelayed(r, delay);
}
Runnable r=new Runnable()
{
public void run()
{
if(ammo_remaining<10)
{
update_ammo();
}
handler.postDelayed(r, period);
};
};
I have a timer in android to countdown to a future date, but it is not refreshing. Any help appreciated. my code is posted below:
public class Activity1 extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView t = (TextView)findViewById(R.id.countdown);
t.setText(timeDif());
I believe that t.setText just needs to be constantly updated, but am unsure of how to do that.
}
public String timeDif()
{
GregorianCalendar then = new GregorianCalendar(2012, 07, 21, 6, 0, 0);
Calendar now = Calendar.getInstance();
long arriveMilli = then.getTimeInMillis();
long nowMilli = now.getTimeInMillis();
long diff = arriveMilli - nowMilli;
int seconds = (int) (diff / 1000);
int minutes = seconds / 60;
seconds %= 60;
int hours = minutes / 60;
minutes %= 60;
int days = hours / 24;
hours %= 24;
String time = days + ":" +zero(hours)+":"+zero(minutes)+":"+zero(seconds);
return time;
}
private int zero(int hours) {
// TODO Auto-generated method stub
return 0;
}
}
The textbox wont update unless you do it in its own thread. The Timer runs on a different thread than the UI. Here is how I did it.
myTimer = new Timer();
myTimerTask = new TimerTask() {
#Override
public void run() {
TimerMethod();
}
};
myTimer.schedule(myTimerTask, 0, 100);
private void TimerMethod()
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
if (isPaused != true) {
this.tmrMilliSeconds--;
this.runOnUiThread(Timer_Tick);
}
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
if (tmrSeconds > 0) {
if (tmrMilliSeconds <= 0) {
tmrSeconds--;
tmrMilliSeconds = 9;
}
} else {
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(1000);
myTimer.cancel();
tmrSeconds = setTime;
tmrMilliSeconds = 0;
isPaused = true;
}
//Do something to the UI thread here
timerText.setText(String.format("%03d.%d", tmrSeconds, tmrMilliSeconds));
}
};
That is part of the code for a count down clock I made for an ap. It demonstrates how to have one thread run (The public void run()) part, and then another part that runs on the UI thread. Hope that helps.
You shouldn't be doing this with a timer. A timer uses a thread and you don't need one (and it complicates things unnecessarily). You need to use a Runable and Handler's postDelayed method to do it. It is easier and lighter weight.
Handler mHandler = new Handler();
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
//update here
mHandler.postDelayed(mUpdateTimeTask, 100);
}
};
private void startTimer()
{
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
I am using below code for scheduling a task in android but its not giving any results. Please advise on the same.
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Toast.makeText(getApplicationContext(),"RUN!",Toast.LENGTH_SHORT).show();
}
}, delay, period);
TimerTasks are not ideal to use in an android environment because they're not context-aware. If your context goes away, the TimerTask will still wait patiently in the background, eventually firing and potentially crashing your app because its activity was previously finished. Or, it may keep references to your activity around after it's been closed, preventing it from being garbage collected and potentially making your app run out of memory.
Instead, use postDelayed(), which will automatically cancel the task when the activity is shut down.
final int delay = 5000;
final int period = 1000;
final Runnable r = new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(),"RUN!",Toast.LENGTH_SHORT).show();
postDelayed(this, period);
}
};
postDelayed(r, delay);
By the way, if you ever need to cancel your task manually, you can use removeCallbacks(r) where r is the runnable you posted previously.
I got the answer as per below code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Timer timer = new Timer();
timer.schedule(new ScheduledTaskWithHandeler(), 5000);
}
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "Run!",
Toast.LENGTH_SHORT).show();
}
};
class ScheduledTaskWithHandeler extends TimerTask {
#Override
public void run() {
handler.sendEmptyMessage(0);
}
}