3

What I want: The user keeps the button clicked for 1900ms. If he picks his finger before 1900ms the phone stops vibrating. While if he keeps his finger on the button for more than 1900 sec, calculate() method runs. I am using: postDelayed as I read it does not interfere with ui thread. I was trying to check if 1900 sec has passed user has not picked his finger, even than calculate method runs. Error Happening: If the user picks his finger before 1900 seconds or just he touches and immediately picks, the phone keeps vibrating. Although it should not happen as I am checking it with MotionEvent.ACTION_UP. Please help !!

  int flag = 0;
  int aborted_flag = 0;
 @Override
public boolean onTouch(View v, MotionEvent event) {

    Handler mHandler = new Handler();

    if(event.getAction()==MotionEvent.ACTION_DOWN){
        scanning();
        t1 = System.currentTimeMillis();
        vibrator.vibrate(1900);

        mHandler.postDelayed(new Runnable() {
            public void run() {
               check();
            }
        }, 1901);
    }

    if(event.getAction()==MotionEvent.ACTION_UP){
        if(flag == 0){
            t2 = System.currentTimeMillis();
            vibrator.cancel();
            calculate();
            aborted_flag = 1;
        }
    }

    return true;
}

private void check() {
    t2 = System.currentTimeMillis();
    Log.e("Hello","Inside Check");
    Log.e("Hello",""+aborted_flag);
    vibrator.cancel();
    if(aborted_flag==0){
        calculate();
        flag = 1;
    }
}

private void scanning() {
    textView.setText("Scanning");
}

private void calculate() {
    Log.e("t2-t1 ", t2-t1+"");

    if(t2-t1>=1900){
        Random r = new Random();
        int k = r.nextInt((5 - 0) + 1) + 0;
        textView.setText(str[k]);

        ////////////animation library code/////////////
        YoYo.with(Techniques.StandUp)
                .duration(700)
                .playOn(findViewById(R.id.text_view));
        ////////////////////////////////////////

        changeBackgroundColor(k);

        //textView.setTextColor(Color.parseColor("#00ff00"));
         flag = 0;
    }
    else{
        textView.setText("Aborted\n Try Again");
        relativeLayout.setBackgroundResource(R.color.red);
    }
}
public void changeBackgroundColor(final int k) {
    runOnUiThread(new Runnable(){
        public void run() {
            switch(k){
                case 0: relativeLayout.setBackgroundResource(R.color.blue);
                    break;
                case 1: relativeLayout.setBackgroundResource(R.color.pink);
                    break;
                case 2:;
                case 3: relativeLayout.setBackgroundResource(R.color.green);
                    break;
                default:relativeLayout.setBackgroundResource(R.color.yellow);
            }
        }
    });
}

3 Answers3

5

If you call postDelayed from the UI thread then your code will be executed on the UI thread.

To use a different thread create one:

Thread t = new Thread(new Runnable(){});
t.start();
darnmason
  • 2,672
  • 1
  • 17
  • 23
  • but then how to wait for 1900ms – Prashant Skywalker Jan 28 '15 at 20:52
  • Thread t = new Thread(new Runnable(){ @Override public void run() { try{ Thread.sleep(1900); check(); } catch(Exception e){ e.printStackTrace(); } } }); t.start(); But its not helping. But what is happening is that if he keeps his finger touched, the calculate method is not running – Prashant Skywalker Jan 28 '15 at 20:55
1

You can create a HandlerThread and use it's looper to create a handler and then post stuff to it either post or postdelayed

public class myActivity extends Activity
{
    private HandlerThread loaderThread;
    private Handler loader;

    @override
    public void onResume()
    {
        super.onResume();

        if (loaderThread == null)
        {
            loaderThread = new HandlerThread("MyActivitySeparateThread");
            loaderThread.start();
            loader = new Handler(loaderThread.getLooper());
        }
    }

    @override
    public void onDestroy()
    {
        //Stop and release handler
        try {
            loader.removeCallbacksAndMessages(null);
            loader.dispose();
        } finally {
            loader = null;
        }

        //Stop and release Thread
        try {
            loaderThread.quit();
            loaderThread.dispose();
        } finally {
            loaderThread = null;
        }

        super.onDestroy();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        switch(event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                {
                    scanning();
                    t1 = System.currentTimeMillis();
                    vibrator.vibrate(1900);

                    loader.postDelayed(new Runnable()
                    {
                        public void run()
                        {
                            check();
                        }
                    }, 1901);
                    break;
                }
            case MotionEvent.ACTION_UP:
                {
                    if (flag == 0)
                    {
                        t2 = System.currentTimeMillis();
                        vibrator.cancel();
                        calculate();
                        aborted_flag = 1;
                    }
                    break;
                }
        }

        return true;
    }
}
Pierre
  • 8,397
  • 4
  • 64
  • 80
0

Because in mHandler.postDelayed you call check() which calls calculate() which calls relativeLayout.setBackgroundResource(). UI can be changed only from UIThread.

Make function:

public void changeBackgroundColor(final int color) {
   runOnUiThread(new Runnable(){
        public void run() {
           relativeLayout.setBackgroundResource(color);
          }
    });
}

And call it from your calculate() function.

kroky
  • 195
  • 2
  • 14
  • I edited the code as you said and a little minor change also by adding aborted_flag. What I wants is if the user does not pick his finger even after 1900 ms, the calculate() method runs and screen color changes. But what is happening is that if he keeps his finger touched, the calculate method is not running. – Prashant Skywalker Jan 28 '15 at 20:45