Android stop loop by click button - java

i am trying to make a button that when its clicked , it changes its color image and starts a countdowntimer in a method activeDelay() as here:
piscaAutoButton = (Button) rootView.findViewById(R.id.piscaAutoButton);
piscaAutoButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(final View view) {
if (sessionManager.getPisca()) {
sessionManager.setPisca(false);
trigger = false;
piscaAutoButton.setBackgroundResource(R.drawable.button_bg_round);
} else {
sessionManager.setPisca(true);
piscaAutoButton.setBackgroundResource(R.drawable.button_add_round);
trigger = true;
activeDelay(trigger);
}
here is my activeDelay method:
private boolean activeDelay(boolean trigger) {
while (trigger) { // LOOP WHILE BUTTON IS TRUE CLICKED
int timerDelay = manualControl.getDelayPisca(); //input for timer
//delay manual
new CountDownTimer(timerDelay * 1000, 1000) {
public void onFinish() {
System.out.println("sent");
try {
System.out.println("blink button " + manualControl.getBlinkButton());
if (!manualControl.getBlinkButton().isEmpty()) {
MenuActivity.mOut.write(manualControl.getBlinkButton().getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void onTick(long millisUntilFinished) {
}
}.start();
}
return trigger;
}
My problem is that i need the counter keeps going after finished, stopping just when the user clicks again in the button (trigger = false). I am having problems to program that, if someone could help,i know the return inside activeDelay ejects from the method, how can we solve that ,tks

I would suggest you to don't use CountDownTimer(this runs for some specific time period) , instead of this you should use Handler(this run infinitely) . i am sending you handler code.
private Handler handler = new Handler();
//call this when you want to start the timer .
handler.postDelayed(runnable, startTime);
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do here , whatever you want to do(show updated time e.t.c.) .
handler.postDelayed(this, xyz); //xyz is time interval(in your case it is 1000)
}
};
//Stop handler when you want(In your case , when user click the button)
handler.removeCallbacks(runnable);

Related

how to set different onclicklisteners on same button click?

I am implementing a timer in android with one text view and one button for start/stop.
How do I set register different events on clicklistener of the same button, such that when it is clicked the first time it will start a timer and when clicked a second time it will stop the timer and report the time between events?
I am implementing a timer in android with one text view and one button for start/stop.
How do I set register different events on clicklistener of the same button, such that when it is clicked the first time it will start a timer and when clicked a second time it will stop the timer and report the time between events?
Edit1
what i did is,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_depth);
findViewById(R.id.btn).setOnClickListener(this);
}
boolean showingFirst = true;
public void generate(View view){
if(showingFirst){
long startTime = System.currentTimeMillis();
showingFirst = false;
}else{
long difference = System.currentTimeMillis() - startTime;
showingFirst = true;
TextView myText = (TextView)findViewById(R.id.tv);
myText.setText(String.valueOf(difference));
}
}
but since long starttime is started in if when the control enters else loop it shows
cannot resolve symbol 'startTime'
please help and special thanks to eliamyro
You can do it using a global boolean isStart and start or stop the timer depending on the value of the isStart.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isStart) {
// Stop timer
isStart = false;
} else {
// Start timer
isStart = true;
}
}
});
try this,
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(btn.getText().toString().equals("Start")){
btn.setText("Stop");
// start timer
}else{
btn.setText("Start");
// stop timer
}
}
});
on click (start/stop) button start the timer according to your code and return a value to button and when you click again that flag value can be used to create a if condition for stop as well as start
As you are starting and stopping a Timer with your button you can just check if the timer is running or not. I would suggest extending a TimerTask for that use case (I took that code from here):
public class YourTimerTask extends TimerTask {
private boolean isRunning = false;
#Overrides
public void run() {
this.isRunning = true;
//rest of run logic here...
}
public boolean isRunning() {
return this.isRunning;
}
}
Then in your onClickListener you can just check if your timer is running or not:
startStopBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (yourTimer.isRunning()) {
stopTimer();
} else {
startTimer();
}
}
});

Display a Toast when a button is clicked frequently

I am new to Android development so excuse me for this question.
So I have a button that when clicked, it will call a method called btnDelay(btnName).
Inside that method is this line of codes:
private void btnDelay(final Button btn){
btn.setEnabled(false);
/*if (counter == 0){
counter++;
}*/
Timer buttonTimer = new Timer();
buttonTimer.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setEnabled(true);
}
});
}
}, 5000);
}
That will disable the button for 5 seconds.
Now what I want to do is when the user clicks the button again and the 5 seconds is not finished, will display a Toast stating that the user's action is too frequent.
Is there a way I can do this? I am thinking of using a counter that will count how many times the user clicked that specific button and will reset to 0 after the 5 seconds on the TimerTask is done. But is there a simplier way to do that? Thank you.
Your button won't fire an onClick event if it's disabled. So instead of disabling it, set the colours to grey or something so it looks disabled and then in your onClick handler for the button:
if(enabled){
btnDelay();
}
else {
sendAToast();
}
Then in btnDelay(), set enabled = false (and set the colours to grey if you want), and inside run() set enabled = true.
Also don't forget to private boolean enabled = true at the top of your class :)
You should declare a Boolean variable for button state. Because if you write btn.setEnabled(false); ,buttonClickEvent can not be triggered for five seconds.
boolean btnState = true;
private void btnDelay(final Button btn){
if (btnState){
Timer buttonTimer = new Timer();
buttonTimer.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
btnState = false;
}
});
}
}, 5000);
}else{
Toast.makeText(this, "your_message", Toast.LENGTH_SHORT).show();
}
}

CountDownTimer variable

I have a major problem about changing the value from a constructor
This is an app for flashlights. It will connect to a site to check the interval value (ex. 500 ms) and it will store it to an variable named frum_timer every 2 seconds.
Here's a object for that.
(also it will update a boolean if there's a new value)
FlashActivity = new CountDownTimer(40000, frum_timer) {
#Override
public void onTick(long millisUntilFinished) {
stats_of_run = true;
if (bool) {
final_form.setText("\\Flash ON//");
// CAMERA INSTRUCTIONS FOR OPENING FLASH
bool = false;
frumtimer_stats.setText("Speed:" + frum_timer);
} else {
stats_of_run = true;
final_form.setText("->Flash OFF-<");
// CAMERA INSTRUCTIONS FOR CLOSING FLASH
bool = true;
}
}
#Override
public void onFinish() {
}
}.start();
I made another CountDownTimer object with a refresh rate of 200 seconds to make sure the frum_timer from FlashActivity object will take change.
and using this
frumtimer_stats.setText("Speed:" + frum_timer);
in FlashActivity for displaying the variable.
However, after the variable frum_timer is changed, the FlashLight keep going again and again at the same old speed even if a made an FlashActivity.cancel() followed by FlashActivity.start()
Can someone give me some help?
Full link of code:
https://mycodestock.com/public/snippet/14395
Summary:
1.You start the app.
2. Refresh countdown starts in 2 sec
3. When there is a frum_timer the FlashActivity will start. After 2 sec, if there is another value stored on frum_timer, the actual FlashActivity will be canceled and will start a new one.
4.The problem is the new FlashActivity start but with the old frum_timer
I used:
public void startProgress(View view) {
// do something long
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 20; i++) {
final int value = i;
doFakeWork();
progress.post(new Runnable() {
#Override
public void run() {
// text.setText("Updating");
progress.setMax(20);
progress.setProgress(value);
}
});
}
}
};
new Thread(runnable).start();
}
private void doFakeWork() {
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Java / Android wait until a thread has finished before running a new method

I have an android application (written in java) which has two buttons (connect and request data).
When each button is clicked, a task is performed and a progress dialog appears to display how much the task has completed.
In order to show the progress dialog, when each button is clicked, the task is run on a thread.
The connect button just has one task - run on the thread. However, the request data button executes two tasks - the first task on the thread similar to the connect button but also a second task, refreshInfo() which must be run after the first task on the thread, progThread is finished.
private Button connectButton;
private Button requestDataButton;
private ProgressDialog connectionDialog;
private ProgressDialog requestDataDialog;
private ProgressThread progThread;
private int currentDialog;
public void connectClick(View view) //When the connect button is clicked
{
performAction(1); //Run the thread to perform the action
}
public void requestDownloadClick(View view) //When the request data button is clicked
{
performAction(2); //Run the thread to perform the action
refreshInfo(); //Do something else
}
private void performAction(int type)
{
currentDialog = type;
showDialog(type);
try
{
progThread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
The key method here is performAction(int type). I basically don't want this method to complete until progThread has finished running.
As you can see, I've tried progThread.join() to prevent the method from continuing until progThread has finished running, however as progThread involves displaying a Progress Dialog, running progThread.join() seems to prevent the Progress Dialog from showing, as currently when you click the button, the first task is performing but the dialog only flashes up at the end.
Can anyone think of a way to run the thread, showing the Progress Dialog as normal and then running the second method (if there is one).
I've included the thread code below incase it is needed.
private class ProgressThread extends Thread
{
final static int DONE = 0;
final static int RUNNING = 1; // Class constants defining state of the thread
private Handler progressHandler;
int mState;
int total;
ProgressThread(Handler _handler) // Constructor with an argument that specifies Handler on main thread to which messages will be sent by this thread.
{
progressHandler = _handler;
}
public void run() // Invoked automatically when the Thread starts.
{
mState = RUNNING;
updateProgressBar();
connectButton = (Button) findViewById(R.id.btnConnect);
requestDataButton = (Button) findViewById(R.id.btnRequestDownload);
while (mState == RUNNING)
{
if (currentDialog == 1)
{
try
{
doSomething();
if (something)
{
setState(DONE);
total = 100;
updateProgressBar();
removeDialog(1);
connectButton.setEnabled(false);
}
else
{
total = total + 20;
if (something has reached a limit)
{
setState(DONE);
total = 0;
updateProgressBar();
removeDialog(1);
}
}
updateProgressBar();
}
catch (Exception e)
{
}
}
if (currentDialog == 2)
{
try
{
doSomething();
total = 10;
updateProgressBar();
doSomething();
total = 70;
updateProgressBar();
if (something) //If the download info has not been got
{
setState(DONE);
total = 0;
updateProgressBar();
removeDialog(2);
runOnUiThread(new Runnable()
{
public void run()
{
connectButton.setEnabled(true);
requestDataButton.setEnabled(true);
}
});
}
else
{
total = 100;
updateProgressBar();
setState(DONE);
removeDialog(2);
runOnUiThread(new Runnable()
{
public void run()
{
requestDataButton.setEnabled(false);
}
});
}
}
catch (Exception e)
{
removeDialog(2);
setState(DONE);
runOnUiThread(new Runnable()
{
public void run()
{
connectButton.setEnabled(true);
requestDataButton.setEnabled(true);
}
});
}
}
}
}
// Set current state of thread (use state=ProgressThread.DONE to stop thread)
public void setState(int state)
{
mState = state;
}
public void updateProgressBar()
{
Message msg = progressHandler.obtainMessage(); // Send message (with current value of total as data) to Handler on UI thread so that it can update the progress bar
Bundle b = new Bundle();
b.putInt("total", total);
msg.setData(b);
progressHandler.sendMessage(msg);
}
}
final Handler handler = new Handler() // Handler on the main (UI) thread that will receive messages from the second thread and update the progress.
{
public void handleMessage(Message msg)
{
int total = msg.getData().getInt("total"); // Get the current value of the variable total from the message data and update the progress bar
switch (currentDialog)
{
case 1 :
connectionDialog.setProgress(total);
break;
case 2 :
requestDataDialog.setProgress(total);
break;
}
}
};
protected Dialog onCreateDialog(int id)
{
switch (currentDialog)
{
case 1 :
connectionDialog = new ProgressDialog(this);
connectionDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
connectionDialog.setMax(100);
connectionDialog.setProgress(0);
connectionDialog.setMessage("Connecting To The Device");
progThread = new ProgressThread(handler);
progThread.start();
return connectionDialog;
case 2 :
requestDataDialog = new ProgressDialog(this);
requestDataDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
requestDataDialog.setMax(100);
requestDataDialog.setProgress(0);
requestDataDialog.setMessage("Requesting Download Data");
progThread = new ProgressThread(handler);
progThread.start();
return requestDataDialog;
default :
return null;
}
}
Android API provides an AsyncTask class which has two methods doInBackground and onPostExecute. You'll have to override both of them, do whatever you have to do in doInBackground and when the job is done onPostExecute callback will be run.
There's also an onProgressUpdate callback which is exactly what you need.
Look at AsyncTask class. It should be able to do what you want.
http://developer.android.com/reference/android/os/AsyncTask.html
Seems other answers have you covered. AsyncTask is the way to go.
However if you want to push through with your Thread implementation, just start() the next thread at the end of the first thread's run method.
Sounds like you need to use a CountdownLatch of size 1

Avoid multi-click in image view android

I try to use this code to prevent multi-click in ImageView but it doesn't help.
Boolean isClicked = false;
#Override
public void onClick(View v)
{
if (v == imgClick && !isClicked)
{
//lock the image
isClicked = true;
Log.d(TAG, "button click");
try
{
//I try to do some thing and then release the image view
Thread.sleep(2000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
isClicked = false;
}
}
In the log cat, I can see 5 lines "button click" when I click on ImageView for 5 times as quickly as possible. I can see the log cat print the first line, wait for a while (2 seconds) and then print the next line. I think when I click the ImageView, the fired event is moved to queue in order, isn't it?. So how can I stop that?
I also try to use setEnable() or setClickable() instead of isClicked variable but it doesn't work too.
Just try this working code
Boolean canClick = true; //make global variable
Handler myHandler = new Handler();
#Override
public void onClick(View v)
{
if (canClick)
{
canClick= false; //lock the image
myHandler.postDelayed(mMyRunnable, 2000);
//perform your action here
}
}
/* give some delay..*/
private Runnable mMyRunnable = new Runnable()
{
#Override
public void run()
{
canClick = true;
myHandler.removeMessages(0);
}
};
Instead of sleeping in 2 seconds, I use some task like doSomeThing() method (has accessed UI thread), and I don't know when it completed. So how can I try your way?
//I referred this android link. You can handle thread more efficiently but i hope below code will work for you..
//you try this and
Boolean canClick = true; //make global variable
public void onClick(View v) {
if(canClick){
new DownloadImageTask().execute();
}
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... urls) {
Log.d("MSG","Clicked");
canClick =false;
//perform your long operation here
return null;
}
protected void onPostExecute(Bitmap result) {
canClick =true;
}
}
You could keep track of the last consumed click upon your View, and based on it either perform the necessary actions, or simply return:
private long calcTime;
private boolean isClickedLately(final long millisToWait)
{
if (System.currentTimeMillis() - calcTime < millisToWait)
return true;
return false;
}
#Override
public void onClick(View v)
{
if (isClickedLately(2000))
return;
calcTime = System.currentTimeMillis();
Log.d(TAG, "consuming button click");
// perform the necessary actions
}
With the millisToWait parameter you can adjust the threshold of "waiting", but if you know that you want to wait exactly 2 seconds between two consecutive clicks, you can eliminate it.
This way you don't have to deal with Threads, which is good, since it's not a great idea to make the gui thread wait.

Categories