Stop timer in onDestroy() - android

Hi guys i want stop my timer in method onDestroy but i don't know what's the best solution...
I have tried timer.purge() in onDestroy but get an error...
#Override
public void onDestroy(){
final ToggleButton btnImbarco = (ToggleButton) findViewById(R.id.toggleButton1);
final ToggleButton btnAtterraDecolla = (ToggleButton) findViewById(R.id.toggleButton3);
final ToggleButton btnRitardo = (ToggleButton) findViewById(R.id.toggleButton2);
if(!btnImbarco.isChecked() && !btnAtterraDecolla.isChecked() && !btnRitardo.isChecked())
//STOP TIMER HERE
}
public void callAsynchronousTask(final TextView attendere,
final ToggleButton btnAtterraDecolla, final ToggleButton btnRitardo, final ToggleButton btnImbarco)
{
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
FlightTask aTask = new FlightTask(attendere,btnAtterraDecolla,btnRitardo,btnImbarco);
if(btnAtterraDecolla.isChecked())
..........
if(btnRitardo.isChecked())
...........
if(btnImbarco.isChecked())
........
aTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, TEMPO_ESECUZIONE_THREAD); //execute in every 50000 ms
}
#Override
protected void onCreate(Bundle savedInstanceState) {
......
Can you help me please?
I want only stop the timer when activity is destroyed!
Thank you...

I usually cancel the timer this way:
I have a boolean set to true when i start the timer, then check it in onDestroy
#Override
public void onDestroy() {
stopUpdates();
super.onDestroy();
}
private void stopUpdates() {
if (isTimerRunning) {
updateTimer.cancel();
updateTimer.purge();
updateTimer = null;
isTimerRunning = false;
}
}
http://developer.android.com/reference/java/util/Timer.html#cancel()

Related

Infinite loop activity when using setRequestedOrientation() in API 19 (KitKat)

The 'setRequestedOrientation' method restarts the activity normally on any version of the android higher than Kitkat.
But in Kitkat, even using if, the activity continues to restart.
int orientation = getResources().getConfiguration().orientation;
// Doesn't work
if (orientation != ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
// Doesn't work
if (orientation != Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
EDIT 1 - StackTrace:
https://gist.github.com/sshnakamoto/11ef6179a561054e54ec4d41a03238f0
Sorry, my log is too long to post here. I've created a gist. But essentially you will see a loop between onCreate() and onStart() methods.
EDIT 2 - ActivityCode:
public class TestActivity extends AppCompatActivity {
private static final String TAG = "TimerActivityCLONE";
private TextView textView;
private ConstraintLayout parentView;
private boolean isColorChanged;
private int textColor;
private int parentColor;
private Handler handler;
private Runnable runnable;
private Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: started ");
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: super called ");
setContentView(R.layout.activity_timer);
Log.d(TAG, "onCreate: setContentView called ");
/* Find on layout*/
parentView = findViewById(R.id.parent);
textView = findViewById(R.id.textView);
textColor = Color.WHITE;
parentColor = Color.BLACK;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
private void initTimer() {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
changeColors();
}
};
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
handler.post(runnable);
}
};
timer = new Timer();
timer.schedule(timerTask, 0, 1000);
}
private void changeColors() {
Log.d(TAG, "changeColors: size " + textView.getTextSize() / getResources().getDisplayMetrics().scaledDensity);
if (isColorChanged){
textView.setTextColor(parentColor);
parentView.setBackgroundColor(textColor);
isColorChanged = false;
} else {
textView.setTextColor(textColor);
parentView.setBackgroundColor(parentColor);
isColorChanged = true;
}
}
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
/* Start to show */
initTimer();
}
#Override
protected void onStop() {
super.onStop();
killTaskAndFinish();
}
#Override
public void onBackPressed() {
super.onBackPressed();
killTaskAndFinish();
}
private void killTaskAndFinish() {
/* Kill background Thread */
timer.cancel();
timer.purge();
handler.removeCallbacks(runnable);
/* Restore user screen orientation */
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
}
}
I've found the bug, it occurs when calling method killTaskAndFinish() inside onStop() due ResquestedOrientation() method restart activity.
But why does this loop only occur on Kitkat (emulator?)? Testing Lollipop it does not happen
I don't know why only occurs on KikKat, but I was able to fix removing handler use. Only TimerTask was need in my case.
This fixes that bug and prevent memory leaks.
#Override
protected void onStart() {
super.onStart();
timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
changeColors();
}
});
}
};
timer = new Timer();
timer.schedule(timerTask, 0, speed);
}
#Override
protected void onStop() {
super.onStop();
timerTask.cancel();
timer.cancel();
timer.purge();
}

Restarting a CountDownTimer in a Dialog window after an OnTouchEvent in a fragment

I have a CountDownTimer that dismisses a dialog popup window. I would like for this timer to restart if the user touches the screen. Here is what I have so far,
public class dataCapture extends Fragment implements OnClickListener {
...
MotionEvent event;
View.OnTouchListener touchListener;
#Override
public void onCreate(Bundle savedDataEntryInstanceState) {
super.onCreate(savedDataEntryInstanceState);
setRetainInstance(true);
}
...
#Override
public View onCreateView
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnHelpFilexml:
openHelpDialog();
break;
...
}
private void openHelpDialog() {
Button btnCloseWindow;
final Dialog helpDialog;
TextView tvHelpDialogTitle, tvHelpDialogBody;
helpDialog = new Dialog(getActivity(), android.R.style.Theme_Translucent);
helpDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
helpDialog.setCancelable(true);
helpDialog.setContentView(R.layout.help_dialog);
tvHelpDialogTitle = (TextView) helpDialog.findViewById(R.id.tvHelpDialogTitle);
tvHelpDialogTitle.setText("DataCapture Help");
tvHelpDialogBody = (TextView) helpDialog.findViewById(R.id.tvHelpDialogBody);
tvHelpDialogBody.setText("Start of help text\n" +
"This is help text\n" +
"\n" +
"Here we go...\n" +
...
"This is the end.");
btnCloseWindow = (Button) helpDialog.findViewById(R.id.btnCloseWindow);
btnCloseWindow.setText("Close");
btnCloseWindow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
helpDialog.dismiss();
}
});
CountDownTimer countDownTimer = new CountDownTimer(30000, 1000) {
// new countDownTimer(30000, 1000) {//makes popup go away after 30 secs
#Override
public void onTick(long millisUntilFinished) {//Do something every second...
}
#Override
public void onFinish() {//action at end of specified time
helpDialog.dismiss();
}
}.start();
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_DOWN) {
countDownTimer.cancel();
countDownTimer.start();
}
return super.onTouchEvent(event);
}
helpDialog.show();
}
}
Any suggestions regarding how best to implement this function would be highly appreciated. Copious TIA.
UPDATE Got it. Solution below. Thanks.
public class dataCapture extends Fragment implements OnClickListener {
...
private static final int COUNTDOWN_TIME_MS = 30000;
Handler handlerHelpDialogTimer;
Runnable runnableHelpDialogDismissCountdown;
Dialog helpDialog;
private Dialog getHelpDialog() {
Button btnCloseWindow;
final Dialog helpDialog;
TextView tvHelpDialogTitle, tvHelpDialogBody;
helpDialog = new Dialog(getActivity(), android.R.style.Theme_Translucent);
helpDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
helpDialog.setCancelable(true);
helpDialog.setContentView(R.layout.help_dialog);
tvHelpDialogTitle = (TextView) helpDialog.findViewById(R.id.tvHelpDialogTitle);
tvHelpDialogTitle.setText("DataCapture Help");
tvHelpDialogBody.setText("Start of help text\n" +
"This is help text\n" +
"\n" +
"Wheee, here we go\n" +
...
"this is the end.");
btnCloseWindow = (Button) helpDialog.findViewById(R.id.btnCloseWindow);
btnCloseWindow.setText("Close");
btnCloseWindow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
helpDialog.dismiss();
}
});
tvHelpDialogBody.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View tvHelpDialogBody, MotionEvent event) {
cancelCountdown();
startCountdown();
return false;
}
});
helpDialog.show();
return (helpDialog);
}
private void showHelpDialog() {
helpDialog = getHelpDialog();
helpDialog.show();
startCountdown();
}
synchronized private void startCountdown() {
handlerHelpDialogTimer.postDelayed(getCountdownTask(), COUNTDOWN_TIME_MS);
}
synchronized private void cancelCountdown() {
handlerHelpDialogTimer.removeCallbacks(runnableHelpDialogDismissCountdown);
runnableHelpDialogDismissCountdown = null;
}
private Runnable getCountdownTask() {
Runnable task = new Runnable() {
#Override
public void run() {
if (helpDialog != null) helpDialog.dismiss();
}
};
runnableHelpDialogDismissCountdown = task;
return task;
}
Ditch the countdown timer. Instead use a handler, for example:
public class AwesomeActivity extends Activity {
private static final int COUNTDOWN_TIME_MS = 300000;
Handler handler;
Runnable countDown;
Dialog helpDialog;
#Override public void onCreate(Bundle b) {
super.onCreate(b);
handler = new Handler();
}
/* call cancelCountdown() in onPause* */
private Dialog getHelpDialog() { return /* fill in the details */ }
private void showHelpDialog() {
helpDialog = getHelpDialog();
helpDialog.show();
startCountDown();
}
synchronized private void startCountDown() {
handler.postDelayed(getCountdownTask(), COUNTDOWN_TIME_MS);
}
synchronized private void cancelCountdown() {
handler.removeCallbacks(countdown);
countdown = null;
}
private Runnable getCountdownTask() {
Runnable task = new Runnable() {
#Override public void run() {
if (helpDialog != null) helpDialog.dismiss();
}
};
countDown = task;
return task;
}
}
Now in onTouch(MotionEvent e) you can cancel and start the countdown.
I'll leave it to you to figure out how to handle onPause and onResume :)
Furthermore, if you really wanted to, you could override a Dialog and put the Handler timer countdown logic inside that class, overriding show() to start the countdown and then add a method such as, restartTimer() you can call after a TOUCH_DOWN. If you do, you can then also override onSaveInstanceState and onRestoreInstanceState in the Dialog subclass, to cancel the callback, stash the time remaining, then pull out the time remaining and re-postdelay the countdown runnable with the remaining time.

Check status thread is activated or no

Hi guys i have a Thread into a Activity.
I want know the status of the thread when i run the Activity...
Is possible know the status of thread?
Example:
if thread not running, start now.
Whenever i run the Activity, the thread start :(
Thread:
public void callAsynchronousTask(Timer timer, final ToggleButton btnAtterraDecolla,
final ToggleButton btnRitardo, final ToggleButton btnImbarco)
{
final Handler handler = new Handler();
isTimerRunning = true;
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
tTask aTask = new tTask(); //THIS IS ASYNCTASK
if(btnAtterraDecolla.isChecked())
LOL(1,AoP,btnAtterraDecolla);
if(btnRitardo.isChecked())
LOL(2,AoP,btnRitardo);
if(btnImbarco.isChecked())
LOL(3,AoP,btnImbarco);
aTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, TEMPO_ESECUZIONE_THREAD); /
}
In onDestroy()
#Override
public void onDestroy() {
stopUpdates(btnAtterraDecolla,btnRitardo,btnImbarco);
super.onDestroy();
}
private void stopUpdates(ToggleButton btnAtterraDecolla,ToggleButton btnRitardo,ToggleButton btnImbarco) {
if(!btnAtterraDecolla.isChecked() && !btnRitardo.isChecked() && !btnImbarco.isChecked()){
if (isTimerRunning) {
timer.cancel();
timer.purge();
timer = null;
isTimerRunning = false;
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....callAsynchronousTask(...)
And here i want stop the thread ONLY IF btn1,btn2,btn3 is NOT checked!
There is a solution for this problem?
Thank you in advance!
There are some way can check the Thread properties
You able to check Thread is Alive() by
Thread.isAlive() ,
method it return boolean.
You able to found running thread run by
Thread.currentThread().getName()

Changing TextView text from a thread

I know you can only change the text in tTxtViews from the UI thread but i cant seem to find a way to work with that.
I'll go in to a bit more details: I'm trying to have a TextView that displays the time passed, but I can't do it in a thread, or a method that keeps getting called.
can you help me with a way of doing this? because I'm pretty much out of ideas.
Thanks.
public class MainActivity extends Activity {
protected static final long TIMER_DELAY = 100;
private TextView tv;
protected Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.helloWorld);
handler = new Handler();
handler.post(timerTask);
}
private Runnable timerTask = new Runnable() {
public void run() {
Calendar now = Calendar.getInstance();
//format date time
tv.setText(String.format("%02d:%02d:%02d", now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND)));
//run again with delay
handler.postDelayed(timerTask, TIMER_DELAY);
}
};
}
I forgot add this, sorry. Don't forget do this:
#Override
public void onPause() {
if (handler != null)
handler.removeCallbacks(timerTask);
super.onPause();
}
And if you want resume app try this
#Override
public void onResume() {
super.onResume();
if (handler != null)
handler.post(timerTask);
}
Use this
new Thread(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do what you want.
}
});
}
}).start();
or use a Handler:
Runnable r = new Runnable() {
#Override
public void run() {
// Do what you want.
}
};
Handler mHandler = new Handler();
mHandler.post(r);

changing image s for 1 second in android imageview

I am trying to change image after 1 second for image view.but its doesn't show any image on screen. following is code.please help.thank you.
code-
public class Shapes extends Activity {
Timer timer = new Timer();
int flag;
String images[]={};
ImageView iv;
static int v[]={R.drawable.round,R.drawable.rectangle};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.shapes);
iv=(ImageView) findViewById(R.id.imageView1);
timer.schedule(new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
if (flag > 1) {
timer.cancel();
timer = null;
} else
iv.setImageResource(v[flag++]);
}
});
}
}, System.currentTimeMillis(), 1000);
}
}
how can i check resource image and change it
Use Handler instead of Timer
Handler handler = new Handler();
Runnable changeImage = new Runnable(){
#Override
public void run(){
if(flag>1)
handler.removeCallbacks(changeImage);
else{
iv.setImageResource(v[flag++]);
handler.postDelayed(changeImage, 1000);
}
}
};
start the first time from oncreate()
public void onCreate(Bundle b){
handler.postDelayed(changeImage, 1000);
}
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
flag++;
if (flag > 1) {
timer.cancel();
timer = null;
}
else
iv.setImageResource(v[flag]);
}
});
}
}, 1000, 1000); // wait 1 second before start.. then repeat every second..
It's because you put System.currentTimeMillis() as delay.
Try replacing that with 0, because the time should start after 0 ms.

Categories

Resources