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()
Related
Using Android studio, I am trying to make an app that gets data from a web-service and display the data and updates the view every 5 sec or when the data on the web-service changes. With this I am trying to change the colours on some button based on an int, the int changes and the color on the button changes when I apply buttons(); to another button and then presses it but I want it to update by itself.
When I used a while loop the app gets stuck
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
buttons();
}
});
The runOnUiThread is placed in the onCreate.
using run on UI thread will cause your UI to freeze , try using a timer task instead .
example :
#Override
public void StopTimerTask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void StartTimer() {
timer = new Timer();
initializeTimerTask();
int UpdateTime = Integer.valueOf(UserSettings.getString("Update", "60000"));
timer.schedule(doAsynchronousTask, 0, YOURTIME);
}
public void initializeTimerTask() {
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
myHandler.post(new Runnable() {
public void run() {
YOUR LOGIC HERE
}
});
}
};
}
doing this where u just put another class into main activity was succesful only problem is that it have to be in my main class
public class updategui extends TimerTask {
Activity context;
Timer timer;
public updategui(Activity context, int seconds) {
this.context = context;
timer = new Timer();
timer.schedule(this,
seconds * 1000, // initial delay
seconds * 1000); // subsequent rate
}
#Override
public void run() {
if(context == null || context.isFinishing()) {
this.cancel();
return;
}
context.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
buttons();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}}
EDIT: I've found that what I'm describing below only occurs on my emulated device (Nexus 5, target api 19, 4.4.2 with Intel Atom (x86) cpu), but NOT on my physical device (HTC One)....
EDIT2: Edit1 was due to an IllegalStateException that I didnt catch. Added some code to check if the thread was already running before trying to start it. This combined with the accepted answer resolved my issue.
I have implemented an activty that starts a new thread in the activity's onCreate method, like this:
...
private boolean running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
running = true;
new Thread(null, work, "myThread").start();
}
Runnable work = new Runnable() {
#Override
public void run() {
while (running) {
//Doing work
}
}
};
I'm "pausing" my thread with my activity's onPause method, like this:
#Override
protected void onPause() {
running = false;
super.onPause();
}
So I thought that resuming it would be just as easy...ยจ
#Override
protected void onResume(){
running = true;
super.onResume();
}
but my thread isn't resuming. Any ideas why? Thankful for any help.
Marcus
All of the answers i think have some issues about your running variable because you can not write and read a variable from two different Threads without synchronized block so i post my own answer:
package com.example.threadandtoast;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public class MonitorObject{
public boolean running = true;
public String message = "";
public boolean mustBePost = true;
}
Thread t;
int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted
// when i pause, you can see it and track it in DDMS
Runnable work = new Runnable() {
boolean myRunning;
#Override
public void run() {
synchronized(mSync) {
myRunning = mSync.running;
}
while (myRunning) {
runOnUiThread(new Runnable() { // in order to update the UI (create Toast)
#Override // we must switch to main thread
public void run() {
// i want to read the message so i must use synchronized block
synchronized(mSync) {
// i use this variable to post a message just for one time because i am in an infinite loop
// if i do not set a limit on the toast i create it infinite times
if(mSync.mustBePost){
Toast.makeText(MainActivity.this, mSync.message, Toast.LENGTH_SHORT).show();
// the message post so i must set it to false
mSync.mustBePost = false;
// if i am going to pause set mSync.running to false so at the end of infinite loop
//of thread he reads it and leaves the loop
if(mSync.message.equals("Main Activity is going to pause")){
mSync.running=false;
}
}
}
}
});
synchronized(mSync) {
myRunning = mSync.running;
}
}
}
};
final MonitorObject mSync = new MonitorObject();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onPause() {
super.onPause();
synchronized(mSync) {
// mSync.running = false; you can not set it here because
// it is possible for the thread to read it and exit the loop before he posts your message
mSync.mustBePost=true;
mSync.message = "Main Activity is going to pause";
}
}
#Override
protected void onResume(){
super.onResume();
threadNameCounter++;
synchronized(mSync) {
mSync.running = true;
mSync.mustBePost=true;
mSync.message = "Main Activity is going to resume";
}
t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
t.start();
}
}
Or you can use this code:
public class MainActivity extends ActionBarActivity {
Thread t;
int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted
// when i pause, you can see it in DDMS
String message = "";
boolean isPost = false;
Runnable work = new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if(!isPost){
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
isPost = true;
if( message.equals("Main Activity is going to pause")){
t.interrupt();
}
}
}
});
if(Thread.currentThread().isInterrupted()){
break;
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onPause() {
super.onPause();
message = "Main Activity is going to pause";
isPost = false;
}
#Override
protected void onResume(){
super.onResume();
message = "Main Activity is going to resume";
isPost = false;
threadNameCounter++;
t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
t.start();
}
}
you can also use semaphore or wait-notify approach.
i put public String message = ""; and public boolean mustBePost = true; in to mSync object but it is
not necessary because only main thread have an access to them.
if you have any problem please ask.
The statement running = false; will stop execution of the Thread, instead of pausing it. Use two variables: One for stopping current Thread, and another for pausing and resuming the Thread, as follow:
boolean isThreadPause=false;
Runnable work = new Runnable() {
#Override
public void run() {
while (running) {
if (!isThreadPause) {
// Doing work
}
}
}
};
In the onPause event of the Activity, set isThreadPause to true, and in the onResume event, set isThreadPause to false.
This is because your Runnable object stops when the while loop stops. You could try this:
Runnable work = new Runnable() {
#Override
public void run() {
while () {
if(running){
//Doing work
}
}
}
};
I am trying to create one application which checks battery status every one minute and update the UI with the battery Level.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
batteryPercent = (TextView) this.findViewById(R.id.battery);
while (true) {
runOnUiThread(mRunnable);
}
}
private Runnable mRunnable = new Runnable() {
#Override
public void run() {
getBatteryPercentage();
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
`getBatteryPercentage()1 update a text view on UI.
When I call getBatteryPercentage() only once the code works fine, but when I try to run it in a loop like above, after few seconds I get Application Not Responding(ANR).
Is there any way to make the app wait for 60 seconds without getting ANR?
Don't do it with Sleep. Use a CountDownTimer instead.
CountDownTimer _timer;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
batteryPercent = (TextView) this.findViewById(R.id.battery);
_timer = new CountDownTimer(Long.MAX_VALUE, 60000) {
#Override
public void onTick(long millisUntilFinished)
{
getBatteryPercentage();
}
#Override public void onFinish() {}
};
_timer.start();
Don't forget to call _timer.cancel() before the Activity exits.
You can use Handler.postDelayed for this.
Handler handler = new Handler();
private Runnable mRunnable = new Runnable() {
#Override
public void run() {
getBatteryPercentage();
handler.postDelayed(mRunnable, 60000);
}
}
And then:
handler.postDelayed(mRunnable, 60000);
if you do something in android uithread more than 5 seconds,the application will show ANR toast.
you should do while loop in another thread,and use callback to refresh ui.you can do it like this:
new Thread(new Runnable(){
public void run(){
try{
Thread().sleep(6*1000);
updateUI();
}catch( Exception e){
e.print***();
}}}).start();
private void updateUI(){
runOnUiThread(new Runnable(){
getBatteryPercentage();
});
}
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()
I am trying to make a clock, using a TextView :)
Someone here told me that I couldn't use normal threads to change the UI, but Handler or AsyncTask. I managed to get it working a few days ago, but was not a consistent thread.
Now what I want is a consistent thread that is always changing the text of my Textview. I tried using this, but didn't work, any help?
private void startClock() {
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
while (true) {
final long millis = System.currentTimeMillis() - MainActivity.startedAt;
clock.setText("" + millis);
runOnUiThread (new Runnable() {
#Override
public void run() {
clock.setText("" + millis);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, 2000);
}
you should get rid of:
while(true) {
....
sleep(1000);
...
}
because this get your thread stuck forever. your program should work like this:
private Handler mHandler = new Handler();
#Override
public void onResume() {
super.onResume();
mHandler.removeCallbacks(mUpdateClockTask);
mHandler.postDelayed(mUpdateCLockTask, 100);
}
#Override
public void onPause() {
super.onPause();
mHandler.removeCallbacks(mUpdateClockTask);
}
private Runnable mUpdateClockTask = new Runnable() {
public void run() {
updateClock();
mHandler.postDelayed(mUpdateClockTask, 2000);
}
};
and inside updateClock() you do all your UI updates.
Look here for an example https://stackoverflow.com/a/11140429/808940
Also note that you have a duplicate line in your code:
clock.setText(""+millis);
It appears both in the runOnUiThread and in the main handler, it should only appear in the runOnUiThread runnable