Handler with ProgressBar - java

Im am trying to create a delayed action, when I touch the Display for more than 5 Seonds.
I am using a Handler and a Runnable for this, using handler.postDelayed(runnable, 5000);
I also want a ProgressBar, to show, when the Handler will kickoff. From researching i found, that i have to Override the handleMessage() method.. this is what i tried.
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progress.setProgress(progress.getProgress() + 100);
sendEmptyMessageDelayed(0, 100);
}
};
private Runnable runnable = new Runnable() {
public void run() {
playAlarm();
}
};
...
progress = (ProgressBar) findViewById(R.id.progressBar1);
...
#Override
public boolean onTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
// Execute Runnable after 5000 milliseconds = 5 seconds.
progress.setProgress(0);
handler.postDelayed(runnable, 5000);
mBooleanIsPressed = true;
}
if (e.getAction() == MotionEvent.ACTION_UP) {
if (mBooleanIsPressed) {
mBooleanIsPressed = false;
progress.setProgress(0);
handler.removeCallbacks(runnable);
}
}
return true;
}
It is not crashing. But the ProgressBar is simply not showing anything.

if you want to use a handler there some things missing, this should work (not tested):
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progress.setProgress(progress.getProgress() + 100);
if (mBooleanIsPressed)
sendEmptyMessageDelayed(0, 100);
}
};
private Runnable runnable = new Runnable() {
public void run() {
playAlarm();
}
};
...
progress = (ProgressBar) findViewById(R.id.progressBar1);
...
#Override
public boolean onTouchEvent(MotionEvent e) {
// only start your handler if the view isn't touched
if (e.getAction() == MotionEvent.ACTION_DOWN && !mBooleanIsPressed) {
// Execute Runnable after 5000 milliseconds = 5 seconds.
progress.setProgress(0);
handler.postDelayed(runnable, 5000);
// send the first empty message, which will be handled...
sendEmptyMessageDelayed(0, 100);
mBooleanIsPressed = true;
}
if (e.getAction() == MotionEvent.ACTION_UP) {
if (mBooleanIsPressed) {
mBooleanIsPressed = false;
progress.setProgress(0);
handler.removeCallbacks(runnable);
}
}
return true;
}
feel free to ask if you have any questions

Related

Why is there no delay on Handler?

I have created a handler for an alert that should activate for 4 seconds, stops for 4 seconds, and activates again. When i put it in the if statement, it doesn't work; the alert keeps playing, stops for less than a second and continues activating again without the delay. Wonder if anyone knows why is it happening and what should i do to correct it. Thank you.
private Handler handler2 = new Handler();
private Runnable startalert = new Runnable() {
#Override
public void run() {
alert2.start();
handler2.postDelayed(this, 4000);
}
};
#Override
public void onLocationChanged(Location location) {
if (location == null) {
speedo.setText("-.- km/h");
}
else {
currentSpeed = location.getSpeed() * 1.85f; //Knots to kmh conversion.
speedo.setText(Math.round(currentSpeed) + " km/h");
}
if (currentSpeed <=4.99) {
background.setBackgroundColor(Color.GREEN);
handler2.removeCallbacks(startalert);
} else if(currentSpeed >=5.00 && currentSpeed <=9.99) {
background.setBackgroundColor(Color.YELLOW);
handler2.removeCallbacks(startalert);
} else if(currentSpeed >=10.00) {
background.setBackgroundColor(Color.RED);
startalert.run();
}
}
Instead of 'this', use runnable object.
private Runnable startalert = new Runnable() {
#Override
public void run() {
alert2.start();
handler2.postDelayed(startalert, 4000);
}
};
Another method:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
alert2.start();
handler.postDelayed(this, 4000);
}
}, 4000);

How to use Handler Postdelayed in queue?

I have a situation, I created a button and a function like this.
...
public void BtnOnClick(View view) {
displayMsg();
}
...
private void displayMsg(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
}
}, 3000);
}
...
If I click the button once a Toast should appear after a 3 seconds delay.
But if I quickly click the button two or more times then all the Toasts appear at the same time after 3 seconds without delay of 3 seconds between every Toast it's not good. I want a 3 seconds gap/delay between every Toast appearance despite of simultaneous clicks.
Is there any solution?
If there are multiple handlers in a queue then each handler delayed time start after the previous handler delay time end.
You can queue the requests to make sure the toasts are displayed at an interval.
ArrayList<Runnable> requests = new ArrayList<>;
bool inProgress = false;
private void displayMsg(){
Runnable runnable = new Runnable() {
#Override
public void run() {
Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
inProgress = false;
if (requests.size() > 0) {
handler.postDelayed(requests.remove(0), 3000 + Toast.LENGTH_SHORT);
}
}
}
if (!inProgress) {
inProgress = true;
handler.postDelayed(runnable, 3000);
} else {
requests.add(runnable);
}
}
Try this:
private final Handler handler = new Handler() {
final int DELAY = 3000;
final int DELAY_MSG = 1;
final Queue<Runnable> pendingRunnables = new ArrayDeque<>();
#Override
public void dispatchMessage(Message msg) {
if (msg.what == DELAY_MSG) {
final Runnable r = pendingRunnables.poll();
if (r != null) {
r.run();
sendEmptyMessageDelayed(DELAY_MSG, DELAY);
}
} else {
pendingRunnables.add(msg.getCallback());
if (!hasMessages(DELAY_MSG)) {
sendEmptyMessage(DELAY_MSG);
}
}
}
};
...
// post action
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
}
});
Maybe you can use postAtTime:
AtomicLong previous = new AtomicLong(System.currentTimeMillis());
private void displayMsg(){
handler.postAtTime(new Runnable() {
#Override
public void run() {
Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
}
}, previous.updateAndGet(operand -> Long.max(operand + 3000, System.currentTimeMillis() + 3000)));
}

Android: Handler.postDelayed doesn't stop

I am unable to stop handler.postDelayed from example below. It simply continues to do function after 1 second, and doesn't stop when switch is off:
mySwitch.setChecked(false);
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
myClient.SendData("AA");
handler.postDelayed(this, 1000);
}
};
if (isChecked){
handler.postDelayed(r, 1000);
}
else {
handler.removeCallbacks(r);
}
}
});
and doesn't stop when switch is off:
that's because you are instantiating r every time the callback is being called. Move
final Runnable r = new Runnable() {
public void run() {
myClient.SendData("AA");
handler.postDelayed(this, 1000);
}
};
outside the callback. In the scope of your method or of the class

onLongclick, text view should increase its value by 1 after every one minute

onLongClick or onLongLouch a TextView , I need to increase its value by 1 every 60 seconds, like this:
<TextView
android:layout_width="match_parent"
android:text="00 min"
android:id="#+id/timer"
android:layout_height="120dp"
/>
Create a Timer that runs each time in miliseconds.
final Handler handlerIncrementar = new Handler();
Timer timerTexto = new Timer();
TimerTask tareaEjecucion = new TimerTask() {
#Override
public void run() {
handlerIncrementar.post(new Runnable() {
public void run() {
try {
yourtextview.setTextSize(yourtextview.getTextSize() + 1);
} catch (Exception e) {
}
}
});
}
};
timerTexto.schedule(tareaEjecucion, 0, 60000);
Below Code will increase the counter by one every one secound till you hold the touch on text view and stops when you relese the touch
private TimerTask timerTask;
private TextView textView;
private int counter = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
textView.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
int code = event.getAction() & MotionEvent.ACTION_MASK;
if (code == MotionEvent.ACTION_DOWN) {
startTimer();
} else if ((code == MotionEvent.ACTION_POINTER_UP) || (code == MotionEvent.ACTION_UP) || (code == MotionEvent.ACTION_CANCEL)) {
stoptimertask();
}
return true;
}
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
Timer timer = new Timer();
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 0, 1000); //
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(counter++ + " Sec");
}
});
}
};
}
I hope this will help you.

How to stop code from running (with timer on ) until a button presses

Is there a way I can do this without having to create new timers and tasks? My code basically scans for wifi signals every 10 seconds. To ensure that the scan returns new results, I used another support class. Can someone verify that there aren't any obvious errors with this as well?
//Inside Button to start scanning
final int DELAY = 10000;
final Handler handler = new Handler();
chkScan.setOnClickListener(new View.OnClickListener() {
final Handler handler = new Handler();
ReceiverWifi = new WifiReceiver();
WIFI_Manager = new wifiScanner();
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
mainWifi.startScan();
if ((WIFI_Manager.resultsAvailable())) {
processResults();
}
// to ensure results come from latest scan
// say there are no new results as of now
WIFI_Manager.waitForNextScan();
}
}
);
timer.schedule(task, 0, DELAY);
}
}
});
}
public void processResults() {
results = mainWifi.getScanResults();
WIFI_Manager.pause() //stop getting wifi results
//continue to process here
//
//
//I wish to put a button here, but and wait for user input before continuing
//but scans continue..
chkLabel.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
}
//more code
// ...
WIFI_Manager.resume();
}
class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
WIFI_Manager.getNewResults();
}
}
public class wifiScanner {
public wifiScanner() {
Pause = false;
new_results = false;
}
public boolean resultsAvailable() {
return new_results;
}
public void waitForNextScan() {
new_results = false;
}
public void getNewResults() {
new_results = true;
}
public boolean onPause() {
return Pause;
}
public void pause() {
unregisterReceiver(receiverWifi);
Pause = true;
}
public void resume() {
registerReceiver(receiverWifi, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
Pause = false;
}
// pause: false- access to scan results are allowed
// pause: true- cannot access scan results
private boolean Pause;
// new_results: false- no new WIFI_resuls
// new_results: true - there are new results to be processed
private boolean new_results;
}
Instead of using a Timer, create a boolean field named stop, and use a while(!stop) loop with Thread.sleep(1000) at the end of an iteration. Your processResults() method will do stop = true; and in your restart button's listener do a stop=false;
But I think it's dirtier than use a Timer ;)

Categories

Resources