1

I'm creating an application that generates some chirp sounds into a "for loop" when a button is pressed, and I want to block the button during the loop, and realease them when the loop is over.

I tried this, but the application crash:

package android.nacho.UltraSoundSender;


import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class UltraSoundSender extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ultra_sound_sender);


        Button btnCode = (Button) findViewById(R.id.btnCode);
        btnCode.setOnClickListener(new OnClickListener() {

            //@Override
            public void onClick(View arg0) {            

                enableButton(false);

                new Thread( new Runnable( ) 
                {
                   public void run( )
                   {   

                       //working=false;
                      // int Code=Integer.parseInt(((EditText)findViewById(R.id.Code)).getText().toString());
                       //((EditText)findViewById(R.id.Code)).setText("");
                       String word= ((EditText)findViewById(R.id.Code)).getText().toString();
                       Integer digits[]= new Integer[64];
                       int NumChar= word.length();

                       //This split the string in chars
                       for(int i = 0; i <  NumChar ; i++){

                           digits[i]=(int)word.charAt(i);

                            }

                      //Values of the chirp
                       int startFreq = 3000;
                       int endFreq = 7000;
                       double impulseDuration = 50;



                       for(int IndexChar= 0; IndexChar< NumChar ; IndexChar++)
                       {

                            new ChirpGenerator().playDOWN(startFreq, endFreq, impulseDuration, digits[IndexChar]);
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                       }


                       enableButton(true);
                   }

                } ).start();

            }
        });


}

    //Enable/disable button
    private void enableButton(boolean isEnable)
    {
        ((Button)findViewById(R.id.btnCode)).setEnabled(isEnable);

}



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_ultra_sound_sender, menu);
        return true;


    }
}

I get this errores in the logcat:

06-19 11:15:00.852: E/AndroidRuntime(29419): FATAL EXCEPTION: Thread-5516 06-19 11:15:00.852: E/AndroidRuntime(29419): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:854) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.view.ViewGroup.invalidateChild(ViewGroup.java:4077) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.view.View.invalidate(View.java:10322) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.widget.TextView.invalidateDrawable(TextView.java:4601) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.graphics.drawable.DrawableContainer.invalidateDrawable(DrawableContainer.java:250) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:338) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.graphics.drawable.Drawable.setVisible(Drawable.java:549) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.graphics.drawable.DrawableContainer.selectDrawable(DrawableContainer.java:307) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.graphics.drawable.StateListDrawable.onStateChange(StateListDrawable.java:106) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.graphics.drawable.Drawable.setState(Drawable.java:465) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.view.View.drawableStateChanged(View.java:14281) 06-19 11:15:00.852: E/AndroidRuntime(29419): at android.widget.TextView.drawableStateChanged(TextView.java:3184)

Where should I call the enabale function? I guess out of the Thread but how?

Ignacio Alorre
  • 7,307
  • 8
  • 57
  • 94
  • 1
    try using `AsyncTask` instead of what you are doing presently. – 7bluephoenix Jun 19 '13 at 09:22
  • Visitors reading this question may wish to check out the solutions at [https://stackoverflow.com/questions/5608720/android-preventing-double-click-on-a-button/12393578] The solution by qezt uses `SystemClock.elapsedRealtime() - mLastClickTime` to determine if the button is recently clicked. – Benjamin Kershner Apr 13 '18 at 18:10

4 Answers4

4

when the button is clicked...and it not clickable until another 5 seconds

btnCode.setOnClickListener(new OnClickListener()
            {
                public void onClick(final View v)
                {
                    v.setClickable(false);
                    new Handler().postDelayed(new Runnable() 
                    {
                        public void run() 
                        {
                            v.setClickable(true);
                        }
                    }, 500);

                }
            });

Replace the time by Your Estimations in for Loop

user2060635
  • 251
  • 1
  • 5
2

How do you expect that your button gets enabled when you enableButton(false) at the end of the thread? Try enableButton(true) instead, I'm sure it is just a typo. :)

Also, in your case, only the UI thread can touch views, have a look at AsyncTask. Basically:

  • disable the button in onPreExecute
  • do the background work in doInBackground
  • enable the button in onPostExecute

Your code needs some refactoring, but it would work at the end.

hundeva
  • 1,058
  • 14
  • 30
  • Sorry guys!! I have edited it, I asked the question with a wrong version. The problem I used to have -and now I have again changing the false-> true- is that I'm trying to enable the button into the thread I creat to generate the chirps, where should I make that call? Thanks for your time – Ignacio Alorre Jun 19 '13 at 09:23
  • I just edited my answer at the same time, have a look at it again. – hundeva Jun 19 '13 at 09:25
2

Yes, it's possible by using setChecked function.
You need to change your button to an ToggleButton
Then

btnCode.setChecked(false);

Your button will be visible but not clickable After treatment, do

btnCode.setChecked(true);
baroni
  • 176
  • 8
  • Sorry guys!! I have edited it, I asked the question with a wrong version. The problem I used to have -and now I have again changing the false-> true- is that I'm trying to enable the button into the thread I creat to generate the chirps, where should I make that call? Thanks for your time – Ignacio Alorre Jun 19 '13 at 09:24
1

Try and set the visibility property of the button as INVISIBLE in the onClick method.

btnCode.setVisibility(View.INVISIBLE);

7bluephoenix
  • 958
  • 7
  • 18
  • thank for the feedback, but actually the "disable" action works, the problem is when I want to enable the button again, once the loop is over. But I will try to set the visibility property as true, just in case. – Ignacio Alorre Jun 19 '13 at 09:12
  • @user1773841 after the loop is over what you do is set the visibility property of the `btnCode` back to **VISIBLE** – 7bluephoenix Jun 19 '13 at 09:14
  • @user1773841 change enableButton(true) after the `for` loop. What you have done is put false instead of true!!! – 7bluephoenix Jun 19 '13 at 09:19
  • Sorry guys!! I have edited it, I asked the question with a wrong version. The problem I used to have -and now I have again changing the false-> true- is that I'm trying to enable the button into the thread I creat to generate the chirps, where should I make that call? Thanks for your time – Ignacio Alorre Jun 19 '13 at 09:23
  • @user1773841 as i commented below your post... try using `AsyncTask` for the goal that you are trying to acheive – 7bluephoenix Jun 19 '13 at 09:25
  • @user1773841 if my suggesstion works for you, please don't forget to mark my answer as accepted ;) – 7bluephoenix Jun 19 '13 at 09:28