I am developing an application, In which I am sending the device location to the server for every one min. I am using Handler here to schedule my task. After User click the STOP button, the handler should stop its execution. I am unable to achieve this. Please find my code below.
public void callSpecficTime() {
timer = new Timer();
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
Log.e("TImeOnSchedule", String.valueOf(inTime));
if(inTime==5)
{
new PostDataAsyncTask().execute();
}
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 60000);
}
StopTask code :
public void stopTask(){
if(doAsynchronousTask!=null){
Log.d("TIMER", "timer canceled");
handler.removeCallbacks(doAsynchronousTask);
// timer.cancel();
doAsynchronousTask.cancel();
}
}
I tried stopService,removeCallbacks but it didn't work. Can anyone provide me solution for this?
UPDATED
public void onClickButton(View v)
{
if(v.getId()==R.id.IBstart)
{
callAsynchronousTask();
callSpecficTime();
}
else if(v.getId()==R.idIBstop)
{
stopTask();
}
}
This is ** callAsynchronousTask()**
public void callAsynchronousTask() {
new PostDataAsyncTask().execute();
}
I am posting data twice. First time is when User click the START button and then I am start the timer to execute for every one min.
use purge() after cancel();
public void stopTask(){
if(doAsynchronousTask!=null){
Log.d("TIMER", "timer canceled");
handler.removeCallbacks(doAsynchronousTask);
// timer.cancel();
doAsynchronousTask.cancel();
doAsynchronousTask.purge();
}
}
You should stop the TimerTask first with: Timer.Cancel() and Timer.Purge().
you can change: handler.removeCallbacks(doAsynchronousTask); to removeCallbacksAndMessages(null).
Edit:
Look at your schedule code: timer.schedule(doAsynchronousTask, 0, 60000); --> that means you start your task immediately and repeated it after 60s.
When I see your onClickButton listener, there are 2 tasks which will be executed immediately. As a result, you cant cancel the tasks which are executed. To avoid it, you can call: timer.schedule(doAsynchronousTask, 60000, 60000);
Related
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
}
};
In my android game, there is an arcade mode, which runs for 60 seconds. UI has to be updated every second. Is it advisable to use CountDownTimer to implement this because as far af i know this class does not run on separate thread ? What are other ways or best way to do this without affecting user experience ?
EXACT CODE WHICH SOLVED MY PROBLEM
new Thread(new Runnable() {
// this creates timer in another thread
#Override
public void run() {
// TODO Auto-generated method stub
long starttime = System.currentTimeMillis();
time=60;
while(time>0)
{
SystemClock.sleep(1000);
long currenttime = System.currentTimeMillis();
time= (int) (60-((currenttime-starttime)/1000));
// this updates the UI
timerhandler.post(new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
tv0.setText(time + " s");
}
});
}
}
}).start();
Use
new Handler().postDelayed(new Runnable(){
#Override
public void run(){
// Your code
}
}, 60*1000));
You can make use of Timer and TimerTask Class. Example (It gives the delay of 6 seconds. Its better to use seperate thread for this)
Timer timer = new Timer("My Timer");
TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("Timer task completed .......");
}
};
System.out.println("Timer task started.......");
timer.schedule(task, 0, 6000);
I have tried multiple ways to have a single persistent timer update the ui in multiple activities, and nothing seems to work. I have tried an AsyncTask, a Handler, and a CountDownTimer. The code below does not execute the first Log.i statement.... Is there a better way to start the timer (which must be called from another class) in Main (which is the only persistent class)?
public static void MainLawTimer()
{
MainActivity.lawTimer = new CountDownTimer(MainActivity.timeLeft, 1000)
{
public void onTick(long millisUntilFinished)
{
Log.i("aaa","Timer running. Time left: "+MainActivity.timeLeft);
MainActivity.timeLeft--;
if(MainActivity.timeLeft<=0)
{
//do stuff
}
else
{
//call method in another class
}
}
public void onFinish()
{ }
}.start();
}
To clarify my problem:
When I run the code the Log.i("aaa","Timer running") statement is never shown in the log, and the CountDownTimer never seems to start. MainLawTimer is called from another class only (not within the same class.
For CountDownTimer
http://developer.android.com/reference/android/os/CountDownTimer.html
You can use a Handler
Handler m_handler;
Runnable m_handlerTask ;
int timeleft=100;
m_handler = new Handler();
#Override
public void run() {
if(timeleft>=0)
{
// do stuff
Log.i("timeleft",""+timeleft);
timeleft--;
}
else
{
m_handler.removeCallbacks(m_handlerTask); // cancel run
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
Timer
int timeleft=100;
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
Log.i("timeleft",""+timeleft);
//update ui
}
});
if(timeleft>==0)
{
timeleft--;
}
else
{
_t.cancel();
}
}
}, 1000, 1000 );
You can use a AsyncTask or a Timer or a CountDownTimer.
Thank you all for your help, I discovered the error in my code... timeLeft was in seconds rather then milliseconds. Since timeLeft was under 1000 (the wait period) the timer never started.
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();