I'm trying to make a timer that will do a certain thing after a certain amount of time:
int delay = 1000;
int period = 1000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
//Does stuff
}
}, delay, period);
However, the app crashes after the wait period. This is Java code, so it might not be entirely compatible with Android (like while loops). Is there something I'm doing wrong?
Something like this should work, create a handler, and wait 1 second :) This is generally the best way of doing it, its the most tidy and also probably the best on memory too as its not really doing too much, plus as it's only doing it once it is the most simple solution.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// do your stuff
}
}, 1000);
If you would like something to run every one second then something like this would be best:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
If you want a GUI thread then something like this should work:
ActivityName.this.runOnUiThread(new Runnable()
{
public void run(){
try {
while(true) {
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
If your app is crashing after the wait period, then your timer task is doing its job and executing your code on schedule. The problem must then be in your code where run() occurs (for example, you may be trying to update UI elements in a background thread).
If you post more code and your logcat, I can probably be more specific about the error you are getting, but your question was in regards to TimerTask.
Timer and also you can run your code on UI thread:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
timerMethod();
}
}, 0, 1000);
}
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.
this.runOnUiThread(timerTick);
}
private Runnable timerTick = new Runnable() {
public void run() {
// This method runs in the same thread as the UI.
// Do something to the UI thread here
}
};
Related
UPDATE : The code is working only that I dint init the textview, but this question is answered so I cant remove it either. So I will leave this question as it is for anyone trying to implement a Timertask with handler that makes use of Looper.getMainLooper that directly attaches it to the UI THREAD.
OLD QUERY :Hello guys I am trying to implement a timer that runs a task which has a handler.
I am using it to update the UI every second.
This is what I am implementing:
private void setRepeatingAsyncTask() {
handler = new Handler(Looper.getMainLooper());
timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
i++;
tview.setText(String.valueOf(i));
} catch (Exception e) {
// error, do something
}
}
});
}
};
timer.schedule(task, 0, 1000); // interval of one minute
}
when I make setRepeatingAsyncTask() on create or somewhere else like button clicklistner, etc either the timer or the handler is not starting.
Please help new to android!
I used Handler to process the task every 1 sec, Using just Handler:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//some task
handler.postDelayed(this, 1000); //looping is every 1 secs
}
}, 0); //initial delay of 0
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();
}
I have this code where I want to try to send an e-mail report every hour (in the example to every second). If there is no coverage, try again within an hour etc. Somehow I managed to break the timer in sendUnsendedReports(): it fires only once. If I remove the call to sendUnsendedReports() than the timer is working perfectly. Even with the try-catch block around it, the timer only fires once. Please advice.
private void createAndScheduleSendReport() {
delayedSendTimer = new Timer();
delayedSendTimer.schedule(new TimerTask() {
#Override
public void run() {
Log.w("UrenRegistratie", "Try to send e-mail...");
try{
sendUnsendedReports();
}
catch(Exception e){
// added try catch block to be sure of uninterupted execution
}
Log.w("UrenRegistratie", "Mail scheduler goes to sleep.");
}
}, 0, 1000);
}
It seems that sometimes timer doesn't works well as it should be. The alternative of this is use of Handler instead TimerTask.
You can use it like :
private Handler handler = new Handler();
handler.postDelayed(runnable, 1000);
private Runnable runnable = new Runnable() {
#Override
public void run() {
try{
sendUnsendedReports();
}
catch(Exception e){
// added try catch block to be sure of uninterupted execution
}
/* and here comes the "trick" */
handler.postDelayed(this, 1000);
}
};
Check out this link for more detail. :)
schedule() can be called in various ways, depending on if you want the task to execute once, or periodically.
To execute the task only once:
timer.schedule(new TimerTask() {
#Override
public void run() {
}
}, 3000);
To execute the task every second after 3 s.
timer.schedule(new TimerTask() {
#Override
public void run() {
}
}, 3000, 1000);
More example usages can be found in the method headers
public void schedule(TimerTask task, Date when) {
// ...
}
public void schedule(TimerTask task, long delay) {
// ...
}
public void schedule(TimerTask task, long delay, long period) {
// ...
}
public void schedule(TimerTask task, Date when, long period) {
// ...
}
It is clearly that you hit the exception and get out of the Timer run method, thus interrupting the timer restart.
I have to display some data after every 10 seconds. Can anyone tell me how to do that?
There is an another way also that you can use to update the UI on specific time interval. Above two options are correct but depends on the situation you can use alternate ways to update the UI on specific time interval.
First declare one global varialbe for Handler to update the UI control from Thread, like below
Handler mHandler = new Handler();
Now create one Thread and use while loop to periodically perform the task using the sleep method of the thread.
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Write your code here to update the UI.
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
Probably the simplest thing to do is this:
while(needToDisplayData)
{
displayData(); // display the data
Thread.sleep(10000); // sleep for 10 seconds
}
Alternately you can use a Timer:
int delay = 1000; // delay for 1 sec.
int period = 10000; // repeat every 10 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
displayData(); // display the data
}
}, delay, period);
Andrahu was on the right track with defining a handler. If you have a handler that calls your update functions you can simply delay the message sent to the handler for 10 seconds.
In this way you don't need to start your own thread or something like that that will lead to strange errors, debugging and maintenance problems.
Just call:
Handler myHandler = new MyUpdateHandler(GUI to refresh); <- You need to define a own handler that simply calls a update function on your gui.
myHandler.sendMessageDelayed(message, 10000);
Now your handleMessage function will be called after 10 seconds. You could just send another message in your update function causing the whole cycle to run over and over
There is Also Another way by Using Handler
final int intervalTime = 10000; // 10 sec
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Display Data here
}
}, intervalTime);
There is a Simple way to display some data after every 10 seconds.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launcher);
ActionStartsHere();
}
public void ActionStartsHere() {
againStartGPSAndSendFile();
}
public void againStartGPSAndSendFile() {
new CountDownTimer(11000,10000) {
#Override
public void onTick(long millisUntilFinished) {
// Display Data by Every Ten Second
}
#Override
public void onFinish() {
ActionStartsHere();
}
}.start();
}
Every 10 seconds automatically refreshed your app screen or activity refreshed
create inside onCreate() method i tried this code will work for me
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
//CALL ANY METHOD OR ANY URL OR FUNCTION or any view
}
});
}
} catch (InterruptedException e) {
}
}
};t.start();
I developed an application to display some text at defined intervals in the Android emulator screen. I am using the Handler class. Here is a snippet from my code:
handler = new Handler();
Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
}
};
handler.postDelayed(r, 1000);
When I run this application the text is displayed only once. Why?
The simple fix to your example is :
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
Or we can use normal thread for example (with original Runner) :
Thread thread = new Thread() {
#Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(this);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
You may consider your runnable object just as a command that can be sent to the message queue for execution, and handler as just a helper object used to send that command.
More details are here http://developer.android.com/reference/android/os/Handler.html
new Handler().postDelayed(new Runnable() {
public void run() {
// do something...
}
}, 100);
I think can improve first solution of Alex2k8 for update correct each second
1.Original code:
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
2.Analysis
In above cost, assume tv.append("Hello Word") cost T milliseconds, after display 500 times delayed time is 500*T milliseconds
It will increase delayed when run long time
3. Solution
To avoid that Just change order of postDelayed(), to avoid delayed:
public void run() {
handler.postDelayed(this, 1000);
tv.append("Hello World");
}
For repeating task you can use
new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);
call it like
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
}
},500,1000);
The above code will run first time after half second(500) and repeat itself after each second(1000)
Where
task being the method to be executed
after the time to initial execution
(interval the time for repeating the execution)
Secondly
And you can also use CountDownTimer if you want to execute a Task number of times.
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();
//Above codes run 40 times after each second
And you can also do it with runnable. create a runnable method like
Runnable runnable = new Runnable()
{
#Override
public void run()
{
}
};
And call it in both these ways
new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis // to work on mainThread
OR
new Thread(runnable).start();//to work in Background
I believe for this typical case, i.e. to run something with a fixed interval, Timer is more appropriate. Here is a simple example:
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
// If you want to modify a view in your Activity
MyActivity.this.runOnUiThread(new Runnable()
public void run(){
tv.append("Hello World");
});
}
}, 1000, 1000); // initial delay 1 second, interval 1 second
Using Timer has few advantages:
Initial delay and the interval can be easily specified in the schedule function arguments
The timer can be stopped by simply calling myTimer.cancel()
If you want to have only one thread running, remember to call myTimer.cancel() before scheduling a new one (if myTimer is not null)
Handler handler=new Handler();
Runnable r = new Runnable(){
public void run() {
tv.append("Hello World");
handler.postDelayed(r, 1000);
}
};
handler.post(r);
Kotlin
private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
val handler = Handler()
runnable = Runnable {
// do your work
handler.postDelayed(runnable, 2000)
}
handler.postDelayed(runnable, 2000)
}
Java
Runnable runnable;
Handler handler;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
// do your work
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}
If I understand correctly the documentation of Handler.post() method:
Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.
So examples provided by #alex2k8, even though are working correctly, are not the same.
In case, where Handler.post() is used, no new threads are created. You just post Runnable to the thread with Handler to be executed by EDT.
After that, EDT only executes Runnable.run(), nothing else.
Remember:
Runnable != Thread.
Kotlin with Coroutines
In Kotlin, using coroutines you can do the following:
CoroutineScope(Dispatchers.Main).launch { // Main, because UI is changed
ticker(delayMillis = 1000, initialDelayMillis = 1000).consumeEach {
tv.append("Hello World")
}
}
Try it out here!
An interesting example is you can continuously see a counter/stop-watch running in separate thread. Also showing GPS-Location. While main activity User Interface Thread is already there.
Excerpt:
try {
cnt++; scnt++;
now=System.currentTimeMillis();
r=rand.nextInt(6); r++;
loc=lm.getLastKnownLocation(best);
if(loc!=null) {
lat=loc.getLatitude();
lng=loc.getLongitude();
}
Thread.sleep(100);
handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {
Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}
To look at code see here:
Thread example displaying GPS Location and Current Time runnable alongside main-activity's User Interface Thread
now in Kotlin you can run threads this way:
class SimpleRunnable: Runnable {
public override fun run() {
println("${Thread.currentThread()} has run.")
}
}
fun main(args: Array<String>) {
val thread = SimpleThread()
thread.start() // Will output: Thread[Thread-0,5,main] has run.
val runnable = SimpleRunnable()
val thread1 = Thread(runnable)
thread1.start() // Will output: Thread[Thread-1,5,main] has run
}