I have this method to scan Bluetooth LE devices. The scanner runs asynchronously for 10s and then it is interrupted.
public void startScanning() {
Handler handler = new Handler();
final long SCAN_PERIOD = 10000;
handler.postDelayed(new Runnable() {
#Override
public void run() {
btScanner.stopScan(leScanCallback);
}
}, SCAN_PERIOD);
btScanner.startScan(leScanCallback);
}
However, depending on a condition that is verified during the scan (for example, I find a device I was looking for, etc.), I call btScanner.stopScan(leScanCallback). So I don't want to call the stopScan after SCAN_PERIOD otherwise I'd call it twice. How do I avoid the second call?
Try to remove call back:
handler.removeCallbacksAndMessages(null);
Handler handler = new Handler();
Runnable runnableRunner = new Runnable() {
#Override
public void run() {
btScanner.stopScan(leScanCallback);
}
}
public void startScanning() {
final long SCAN_PERIOD = 10000;
handler.postDelayed(runnableRunner, SCAN_PERIOD);
btScanner.startScan(leScanCallback);
}
Use removeCallbacks removes any pending posts of Runnable r that are in the message queue.
// cancel runnable whenever your condition is met.
handler.removeCallbacks(runnableRunner);
or use to remove all messages and callbacks
handler.removeCallbacksAndMessages(null);
I have another question on this problem.
I have a method m() in my "sequential" part of the code, not in the asynchronous one, that I need to call only if either the handler.removeCallbacksAndMessages(null); is called, or after the SCAN_PERIOD has expired. How do I check these conditions and basically wait that one of the two happens? Do I need to put m() in a synchronous run?
(Now I also have the global handler that I can use)
Related
This is my function who run a code every 2.5 seconds and check if a value seted to the true my progress will gone and ...
mHandler = new Handler();
continue_or_stop = true;
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (continue_or_stop) {
try {
Thread.sleep(2500); // every 2.5 seconds
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if (sp.getFromPreferences("state_update").equals("true")) {
progress_main.setVisibility(View.GONE);
layout_main.setVisibility(View.VISIBLE);
btn_save_send.setVisibility(View.GONE);
getOutputs();
MDToast.makeText(getActivity(), "وضعیت دستگاه با موفقیت بروزرسانی شد", Toast.LENGTH_LONG, MDToast.TYPE_SUCCESS).show();
sp.saveToPreferences("state_update", "false");
Intent intent = new Intent(getContext(), MainActivity.class);
startActivity(intent);
}
// you can set continue_or_stop to false, for stop
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
now i want a time out for this method if the value not seted to true after a (for example 12 seconds) progress should gone and Toast it to user that something goes wrong and try again
You can check for the timeout based on the number of trials. Also using thread and Thread.sleep for running a periodic task is not a good practice.
To run a periodic task, you can post a Runnable to a Handler with some delay using postDelayed method.
private Handler mHandler = new Handler();
private int mTrials = 0;
private Runnable mPeriodicTask = new Runnable() {
public void run() {
// Do the check
mTrials += 1;
if (mTrials == /* timeout number */) {
// timeout
} else {
mHandler.postDelayed(this, 2500);
}
}
}
To run the task:
mHandler.postDelayed(mPeriodicTask, 2500);
Apparently this is more Android oriented, but I'll answer in general terms. And the other answer seems lacking the "12 seconds" timeout.
Well, you cannot really terminate a Thread immediatly, or forcely. Consider a Thread like a person, you need to kindly request him to terminate what he's doing. If he is able to do that, he will terminate, if not he will continue with its task.
As you're building the implementation of the task, you can check if someone asked you to terminate, with a special flag
Thread#isInterrupted()
Now, for this kind of thing using an ExecutorService is the better option, as it returns a Future<T> which can be canceled. E.g.
final ExecutorService executorService = ExecutorService.newSingleThreadExecutor();
final Future<?> future = executorService.submit(runnable);
You can then say to the Future "I want the result (which in your case is nothing), but with a timeout"
try {
future.get(12, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
future.cancel(true);
}
The cancel(true) method call will set the interrupted flag of the Thread.
Now, maintaining the code you already have, you might simply want to replace
while (continue_or_stop)
with
while (!Thread.currentThread().isInterrupted())
Adjust to your needs.
In my application i will be keep on updating some info in some time interval.so i have done like this
handler = new Handler();
and then some Task
handler.postDelayed(runLocation, 1000);
public Runnable runLocation = new Runnable(){
#Override
public void run() {
MainActivity.this.handler.postDelayed(MainActivity.this.runLocation, 100);
};
My problem is i want to stop this runnable at some point of time.how to do this ?
Can you help me?
You can use removeCallbacks. Just call
handler.removeCallbacks(runLocation);
it will remove any pending items in the message's queue.
Use removeCallbacks
#Override
public void run() {
if(isStopHandler){
MainActivity.this.handler.removeCallbacks(this);
return;
}
// do your runnable work
// set isStopHandler = true when needed so next time this method is executed, it will get inside if cond.
};
When I start the app "specific function" needs to be executed.
After 10 seconds "specific function" needs to be triggered again.
After this second operation "specific function" should not triggered again.
There are two way to handle your problem.
If there is any condition you want to check and accordingly do the work after every 10 seconds You should Use a Handler.
If there is no condition on anything and you just want to run the code after every 10 Seconds. Then TimerTask is also one way. I have actually worked with TimerTask class. So i say it is quite easy.
Creating your class and implementing the methods.
class myTaskTimer extends TimerTask{
#Override
public void run() {
Log.e("TAG", "run: "+"timer x");
}
}
and now in your code Create a new Timer Object and initialize it.
Timer t = new Timer();
Now you can schedule your task in it after a specified interval like below:
t.scheduleAtFixedRate(new myTaskTimer(),10000,10000);
The function is explained below:
void scheduleAtFixedRate (TimerTask task,
long delay,
long period)
Schedules the specified task for repeated fixed-rate execution,
beginning after the specified delay. Subsequent executions take place
at approximately regular intervals, separated by the specified period.
and now for handler , below is the code and it can check for any condition. Code taken from here for your help.
private int mInterval = 10000; // 10 seconds as you need
private Handler mHandler;
#Override
protected void onCreate(Bundle bundle) {
// your code here
mHandler = new Handler();
startRepeatingTask();
}
#Override
public void onDestroy() {
super.onDestroy();
stopRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try {
updateStatus(); //this function can change value of mInterval.
} finally {
// 100% guarantee that this always happens, even if
// your update method throws an exception
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
I hope it helps.
Use android.os.Handler as per #pskink comment.
private void callSomeMethodTwice(){
context.myMethod(); //calling 1st time
new Handler().postDelayed(new Runnable(){
#Override
public void run(){
context.myMethod(); //calling 2nd time after 10 sec
}
},10000};
}
This is probably a very easy question but, How do I use a timer to run code again and again until a boolean value e.g. Testing is equal to true?
Obviously I would use a while loop but I don't want it to stop the rest of the work taking place on the main ui thread
If your process is running simultaneously, use a Handler and use its postDelayed(Runnable, long) to post a callback implementing the Runnable interface.
A rather naive example:
final handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
if (<EXPRESSION>) {
// Evaluated true, do your stuff and exit the polling loop.
} else {
handler.postDelayed(this, <TIMEOUT>);
}
}
handler.postDelayed(r, <TIMEOUT>);
You can use AlarmManager class to manage your thread. its simple to use.
for more info you can visit Android SDK Doc
timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
if(flagIsOn)
{
timer.cancel();
timer.purge();
}
}
}, 0, 1000);
I am doing a simple Async operation with Android, but since I want to execute the action couple of times, I am not using AsyncTask, I instead use Thread/Runnable mechanism with Handler to handle messages and staff. But at one point when I need to execute the second operation, I need to cancel the previous operation if it is still active.
I have something like this:
private void exec() {
new Thread(new Runnable() {
public void run() {
mBind.exec(3);
}
}).start();
}
Then in exec(int a) I have an interation like:
for(int i = 0; i<=res.lenght; i++) {
updateGui();
}
But at one point the exec() method is called for second time, and the gui is updated with the previous results too (I need only the results from the new (2nd) request).
I know there is way to do this with FutureTask and play with cancel() or with Thread's 'throw ThreadDead' exception, but I am just curious if I can do it the same way I started in the first place.
thanks!
What I have understand from your question is that you want to cancel the currently running thread if the new thread started.
This you can do by calling Thread's interrupt() method, this will interrupt the currently running thread, and throws the InterruptedException.
Thread t1 = null;
private void exec() {
t1 = new Thread(new Runnable() {
public void run() {
mBind.exec(3);
}
}).start();
}
Before calling exec, call t1.interrupt().
Feels a bit dirty, but could you save the name of the most recently activated Thread and check for it in your Handler? Something like:
private static final int MESSAGE_UPDATE_COMPLETE = 0;
private String threadName;
private void exec() {
Thread thread = new Thread() {
public void run() {
// do stuff
...
Message msg = Message.obtain();
msg.what = MESSAGE_UPDATE_COMPLETE;
msg.obj = this.getName();
handler.sendMessage(msg);
}
};
thread.start();
threadName = thread.getName();
}
...
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch(msg.what){
case MESSAGE_UPDATE_COMPLETE:
if (threadName.equals((String)msg.obj)) {
// do UI update
}
break;
...
}
}
}