I have been trying to figure out how to make a countdown timer using 'handler()' and i still don't know how to make it so the app will execute the line "Finished" when the countdown hits 0.
I am after whatever line of code is required for me to enter in the 'UpdateGUI()' to exit the runnable and go back to the main activity to display "Finished".
I have not been coding very long, so maybe it is an obvious answer, but I can't find it on any threads on this page...
Some help would be much appreciated :-)
Thank you
public class MainActivity extends AppCompatActivity {
int i = 10;
TextView tv;
final Handler myHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button but = (Button) findViewById(R.id.button);
but.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tv = (TextView) findViewById(R.id.textView);
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
UpdateGUI();
}
}, 0, 1000);
tv = (TextView) findViewById(R.id.textView);
tv.setText("Finished");
}
});
}
private void UpdateGUI() {
if (i == 0) {
//this is where i need to enter the code!!
}
else
i--;
myHandler.post(myRunnable);
}
final Runnable myRunnable = new Runnable() {
public void run() {
tv.setText(String.valueOf(i));
}
};
}
If I understand you correctly in case you need to run your runnable after some period of time use Handler method postDelayed(runnable, timeOutInMillis)
UPDATE: example of handler timer
int timesRun;
Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
runTimer();
i++;
}
};
// call it in button callback
public void runTimer(){
// update your timer here
if (i != 10) // if 10 seconds not passed run it one more time
handler.postDelayed(runnable, 1000); // run every second
}
Note that this is not the most elegant way to do this, but still, it should work
I have setup a stop watch using the com.apache.commons library and the stop watch seems to work fine. What I don't know how to do is display this stopwatch in a textView in my app. In general, I have no idea how that would work, i.e. How exactly would a stopwatch be displayed in a textView, given that the time on a stopwatch keeps changing constantly? At the moment, I have the code below and it updated the text in the textView every second for about 2 seconds and then I got a weird error. I'm not even sure if this is the right way to go about doing this. Please help!
Timer timer = new Timer();
TimerTask timerTask;
timerTask = new TimerTask() {
#Override
public void run() {
timeText.setText(time.toString());
}
};
timer.schedule(timerTask, 0, 1000);
The error I got after 2 seconds (and it successfully updated the time) was :
"only the original thread that created a view hierarchy can touch its views"
You can only update a TextView on the UI thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
//stuff that updates ui
}
});
Your code becomes
Timer timer = new Timer();
TimerTask timerTask;
timerTask = new TimerTask()
{
#Override
public void run()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
timeText.setText(time.toString());
}
});
}
};
timer.schedule(timerTask, 0, 1000);
You may have to do myActivityObject.runOnUiThread() if you're getting an error there.
See this for more detail.
To update a view from another thread, you should use handler.
private void startTimerThread() {
Handler handler = new Handler();
Runnable runnable = new Runnable() {
private long startTime = System.currentTimeMillis();
public void run() {
//Change the condition for while loop depending on your program logic
while (true) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable(){
public void run() {
timeText.setText(time.toString());
}
});
}
}
};
new Thread(runnable).start();
}
Here's my code:
public class SomeName extends MapActivity implements OnClickListener, OnTouchListener{
public Timer t1 = new Timer();
public TimerTask tt;
public long interval = 5000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.map);
timer();
}
public final void timer()
{
t1 = new Timer();
tt = new TimerTask() {
#Override
public void run() {
systemClick();
}
};
t1.scheduleAtFixedRate(tt, 10000, interval);
}
public void systemClick()
{
Toast.makeText(getApplicationContext(),"System Button Clicked", 5).show();
}
Actually, I want to call some function, where I refresh my location.
But I can't understand why I never get the toast on the screen.
I'm new to android.
Thanks for any help.
use handler in your Activity
final Handler handlerforadd = new Handler();
Runnable runnableforadd = new Runnable() {
#Override
public void run() {
handlerforadd.postDelayed(this, 1000);
}
};
handlerforadd.postDelayed(runnableforadd, 0);
The reason is the Toast has to be done on the UI thread. In your current code the method run() is being executed on a separate thread. I would suggest looking at this article on Processes and Threads. #parag is correct using a Handler is one way to get a reference to the UI thread but there are other methods.
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);
}
}
What is the proper way to set a timer in android in order to kick off a task (a function that I create which does not change the UI)?
Use this the Java way:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html
Or there is a better way in android (android's handler)?
yes java's timer can be used, but as the question asks for better way (for mobile). Which is explained Here.
For the sake of StackOverflow:
Since Timer creates a new thread it may be considered heavy,
if all you need is to get is a call back while the activity is running a Handler can be used in conjunction with a
Runnable:
private final int interval = 1000; // 1 Second
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
public void run() {
Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
}
};
...
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);
or a Message
private final int EVENT1 = 1;
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Event1:
Toast.makeText(MyActivity.this, "Event 1", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(MyActivity.this, "Unhandled", Toast.LENGTH_SHORT).show();
break;
}
}
};
...
Message msg = handler.obtainMessage(EVENT1);
handler.sendMessageAtTime(msg, System.currentTimeMillis()+interval);
handler.sendMessageDelayed(msg, interval);
on a side note this approach can be used, if you want to run a piece of code in the UI thread from an another thread.
WARNING: Handler's timer (or whatever controls delays) gets paused whenever the CPU goes to deep-sleep, but will continue once CPU wakes up (from where it was paused).
if you need to get a call back even if your activity is not running then, you can use an AlarmManager.
Standard Java way to use timers via java.util.Timer and java.util.TimerTask works fine in Android, but you should be aware that this method creates a new thread.
You may consider using the very convenient Handler class (android.os.Handler) and send messages to the handler via sendMessageAtTime(android.os.Message, long) or sendMessageDelayed(android.os.Message, long). Once you receive a message, you can run desired tasks. Second option would be to create a Runnable object and schedule it via Handler's functions postAtTime(java.lang.Runnable, long) or postDelayed(java.lang.Runnable, long).
As I have seen it, java.util.Timer is the most used for implementing a timer.
For a repeating task:
new Timer().scheduleAtFixedRate(task, after, interval);
For a single run of a task:
new Timer().schedule(task, after);
task being the method to be executed
after the time to initial execution
(interval the time for repeating the execution)
I hope this one is helpful and may take less efforts to implement,
Android CountDownTimer class
e.g.
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
Probably Timerconcept
new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
}
}.start();
or
Method 2 ::
Program the timer
Add a new variable of int named time. Set it to 0.
Add the following code to onCreate function in MainActivity.java.
//Declare the timer
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Called each time when 1000 milliseconds (1 second) (the period parameter)
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);
Go into the run method and add the following code.
//We must use this function in order to change the text view text
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView tv = (TextView) findViewById(R.id.main_timer_text);
tv.setText(String.valueOf(time));
time += 1;
}
});
It is situational.
The Android documentation suggests that you should use AlarmManager to register an Intent that will fire at the specified time if your application may not be running.
Otherwise, you should use Handler.
Note: The Alarm Manager is intended
for cases where you want to have your
application code run at a specific
time, even if your application is not
currently running. For normal timing
operations (ticks, timeouts, etc) it
is easier and much more efficient to
use Handler.
Here we go.. We will need two classes. I am posting a code which changes mobile audio profile after each 5 seconds (5000 mili seconds) ...
Our 1st Class
public class ChangeProfileActivityMain extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Timer timer = new Timer();
TimerTask updateProfile = new CustomTimerTask(ChangeProfileActivityMain.this);
timer.scheduleAtFixedRate(updateProfile, 0, 5000);
}
}
Our 2nd Class
public class CustomTimerTask extends TimerTask {
private AudioManager audioManager;
private Context context;
private Handler mHandler = new Handler();
// Write Custom Constructor to pass Context
public CustomTimerTask(Context con) {
this.context = con;
}
#Override
public void run() {
// TODO Auto-generated method stub
// your code starts here.
// I have used Thread and Handler as we can not show Toast without starting new thread when we are inside a thread.
// As TimePicker has run() thread running., So We must show Toast through Handler.post in a new Thread. Thats how it works in Android..
new Thread(new Runnable() {
#Override
public void run() {
audioManager = (AudioManager) context.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
mHandler.post(new Runnable() {
#Override
public void run() {
if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
Toast.makeText(context, "Ringer Mode set to Normal", Toast.LENGTH_SHORT).show();
} else {
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
Toast.makeText(context, "Ringer Mode set to Silent", Toast.LENGTH_SHORT).show();
}
}
});
}
}).start();
}
}
I'm an Android newbie but here is the timer class I created based on the answers above. It works for my app but I welcome any suggestions.
Usage example:
...{
public Handler uiHandler = new Handler();
private Runnable runMethod = new Runnable()
{
public void run()
{
// do something
}
};
timer = new UITimer(handler, runMethod, timeoutSeconds*1000);
timer.start();
}...
public class UITimer
{
private Handler handler;
private Runnable runMethod;
private int intervalMs;
private boolean enabled = false;
private boolean oneTime = false;
public UITimer(Handler handler, Runnable runMethod, int intervalMs)
{
this.handler = handler;
this.runMethod = runMethod;
this.intervalMs = intervalMs;
}
public UITimer(Handler handler, Runnable runMethod, int intervalMs, boolean oneTime)
{
this(handler, runMethod, intervalMs);
this.oneTime = oneTime;
}
public void start()
{
if (enabled)
return;
if (intervalMs < 1)
{
Log.e("timer start", "Invalid interval:" + intervalMs);
return;
}
enabled = true;
handler.postDelayed(timer_tick, intervalMs);
}
public void stop()
{
if (!enabled)
return;
enabled = false;
handler.removeCallbacks(runMethod);
handler.removeCallbacks(timer_tick);
}
public boolean isEnabled()
{
return enabled;
}
private Runnable timer_tick = new Runnable()
{
public void run()
{
if (!enabled)
return;
handler.post(runMethod);
if (oneTime)
{
enabled = false;
return;
}
handler.postDelayed(timer_tick, intervalMs);
}
};
}
I am using a handler and runnable to create a timer. I wrapper this in an abstract class. Just derive/implement it and you are good to go:
public static abstract class SimpleTimer {
abstract void onTimer();
private Runnable runnableCode = null;
private Handler handler = new Handler();
void startDelayed(final int intervalMS, int delayMS) {
runnableCode = new Runnable() {
#Override
public void run() {
handler.postDelayed(runnableCode, intervalMS);
onTimer();
}
};
handler.postDelayed(runnableCode, delayMS);
}
void start(final int intervalMS) {
startDelayed(intervalMS, 0);
}
void stop() {
handler.removeCallbacks(runnableCode);
}
}
Note that the handler.postDelayed is called before the code to be executed - this will make the timer more closed timed as "expected". However in cases were the timer runs to frequently and the task (onTimer()) is long - there might be overlaps. If you want to start counting intervalMS after the task is done, move the onTimer() call a line above.
I believe the way to do this on the android is that you need a background service to be running. In that background application, create the timer. When the timer "ticks" (set the interval for how long you want to wait), launch your activity which you want to start.
http://developer.android.com/guide/topics/fundamentals.html (<-- this article explains the relationship between activities, services, intents and other core fundamentals of Android development)
I used to use (Timer, TimerTask) as well as Handler to kick off (time-consuming) tasks periodically. Now I've switched the whole to RxJava. RxJava provides Observable.timer which is simpler, less error-prone, hassle-free to use.
public class BetterTimerFragment extends Fragment {
public static final String TAG = "BetterTimer";
private TextView timeView;
private Subscription timerSubscription;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_timer, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
timeView = (TextView) view.findViewById(R.id.timeView);
}
#Override
public void onResume() {
super.onResume();
// Right after the app is visible to users, delay 2 seconds
// then kick off a (heavy) task every 10 seconds.
timerSubscription = Observable.timer(2, 10, TimeUnit.SECONDS)
.map(new Func1<Long, String>() {
#Override
public String call(Long unused) {
// TODO: Probably do time-consuming work here.
// This runs on a different thread than the main thread.
return "Time: " + System.currentTimeMillis();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
#Override
public void call(String timeText) {
// The result will then be propagated back to the main thread.
timeView.setText(timeText);
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
Log.e(TAG, throwable.getMessage(), throwable);
}
});
}
#Override
public void onPause() {
super.onPause();
// Don't kick off tasks when the app gets invisible.
timerSubscription.unsubscribe();
}
}
For timing operation you should use Handler.
If you need to run a background service the AlarmManager is the way to go.
this example start the timer unitl destroyed in Kotlin
private lateinit var timerTask: TimerTask
timerTask = object : TimerTask() {
override fun run() {
Log.d("KTZ", "$minutes:$seconds");
timeRecordingLiveData.postValue("$minutes:$seconds")
seconds += 1;
if (seconds == 60) {
Log.d("KTZ", "$minutes:$seconds");
timeRecordingLiveData.postValue("$minutes:$seconds")
seconds = 0;
minutes += 1;
}
}
}
Cancel the timertask in onDestroy()
timerTask.cancel()