Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tap on screen 5 Times in 3 seconds in android

I am developing a kiosk and now in admin side. In order to go to the Admin, the user needs to tap the screen 5 times just in 3 seconds or else, nothing will happen.

like image 639
androidBoomer Avatar asked Jan 14 '14 00:01

androidBoomer


3 Answers

Please read the comments in the code, it is quite straightforward

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;

public class MainActivity extends Activity {

private int count = 0;
private long startMillis=0;

//detect any touch event in the screen (instead of an specific view)

@Override
public boolean onTouchEvent(MotionEvent event) {  

    int eventaction = event.getAction();
     if (eventaction == MotionEvent.ACTION_UP) {

     //get system current milliseconds
     long time= System.currentTimeMillis();


     //if it is the first time, or if it has been more than 3 seconds since the first tap ( so it is like a new try), we reset everything 
     if (startMillis==0 || (time-startMillis> 3000) ) {
         startMillis=time;
         count=1;
     }
     //it is not the first, and it has been  less than 3 seconds since the first
     else{ //  time-startMillis< 3000   
         count++;
     }

     if (count==5) {
        //do whatever you need
     }
     return true;    
    }
    return false;
  }

}
like image 94
Carlos Robles Avatar answered Oct 30 '22 07:10

Carlos Robles


My solution is similar to Andres's. The countdown starts when you lift the finger for the first time, that is, when I consider the tap to be finished. This is similar to clicks, a click occurs when you release the mouse button. After 3 seconds from the first lift, the counter is reset. Andres's approch, on the other side, uses logic based on placing the finger down onto the screen. It also uses an additional thread.

My logic is one of the many possible ones. Another reasonable approach would be to detect 5 consecutive taps within 3 seconds in a stream of taps. Consider:

tap1, 2000ms, tap2, 500ms, tap3, 550ms, tap4, 10ms, tap5, 10ms, tap6.

The second through the sixth tap encompasses a set of five taps in less than 3 seconds; in my approach this would not be detected. To detect this you can use a FIFO queue of fixed size 5 and remember the last 5 timestamps: this sequence is increasing. When you receive a new tap, you check whether 1) there are at least 5 taps occurred, and 2) the oldest timestamp is no older then 3 seconds old.

Anyway, back to the first logic, place this code in an Activity:

private int mCounter = 0;
private Handler mHandler = new Handler();

private Runnable mResetCounter = new Runnable() {
    @Override
    public void run() {
        mCounter = 0;
    }
};

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch(MotionEventCompat.getActionMasked(event)) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (mCounter == 0)
                mHandler.postDelayed(mResetCounter, 3000);

            mCounter++;

            if (mCounter == 5){
                mHandler.removeCallbacks(mResetCounter);
                mCounter = 0;
                Toast.makeText(this, "Five taps in three seconds", Toast.LENGTH_SHORT).show();
            }

            return false;

        default : 
            return super.onTouchEvent(event);
    }
}

Note: you probably want some state retention on configuration changes too. As a mathematician would say, I let that as an exercise to the reader

like image 42
Gil Vegliach Avatar answered Oct 30 '22 07:10

Gil Vegliach


Override your Activity onTouchEvent() method to receive the touch events from the screen. Every time the user taps the screen increment a variable and postpone a Runnable in 3 seconds if it's the first time you touch, if 3 seconds passes the touch events will be cleared and nothing happens. A Thread checks for the touch events number to be 5 or more, if they happened before the 3 seconds the variable is not cleared and the if(touchEvent >= 5) condition is true. I haven't tested it! But it's completely asynchronous :)

// Touch events on screen
@Override
public boolean onTouchEvent(MotionEvent event) {
        // User pressed the screen
        if(event.getAction() == MotionEvent.ACTION_DOWN){
          if(touchEvent == 0) myView.post(mRunnable, 3000);  // Execute a Runnable in 3 seconds
          ++touchEvent;
        }
        return false;
}

Runnable mRunnable = new Runnable(){
        @Override
        public void run() {
           touchEvent = 0; // 3 seconds passed, clear touch events
        }
}

Thread mThread = new Thread(new Runnable(){
   @Override
   public void run(){
      if(touchEvent >= 5){
         // Touched 5 times in 3 seconds or less, CARE this is not UI Thread!
      }
   }
});
mThread.start();
like image 1
Andres Avatar answered Oct 30 '22 08:10

Andres