/** * Wire * Copyright (C) 2016 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * This part of the Wire software uses source coded posted on the StackOverflow site. * (http://stackoverflow.com/a/5117254/257948) * * That work is licensed under a Creative Commons Attribution-ShareAlike 2.5 Generic License. * (http://creativecommons.org/licenses/by-sa/2.5) * * Contributors on SO: * - peceps (http://stackoverflow.com/users/590531) */ package com.waz.zclient.utils.debug; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; /** * Listener that detects shake gesture. */ public class ShakeEventListener implements SensorEventListener { /** Minimum movement force to consider. */ private static final int MIN_FORCE = 16; /** * Minimum times in a shake gesture that the direction of movement needs to * change. */ private static final int MIN_DIRECTION_CHANGE = 4; /** Maximum pause between movements. */ private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200; /** Maximum allowed time for shake gesture. */ private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400; /** Time when the gesture started. */ private long firstDirectionChangeTime = 0; /** Time when the last movement started. */ private long lastDirectionChangeTime; /** How many movements are considered so far. */ private int directionChangeCount = 0; /** The last x position. */ private float lastX = 0; /** The last y position. */ private float lastY = 0; /** The last z position. */ private float lastZ = 0; /** OnShakeListener that is called when shake is detected. */ private OnShakeListener shakeListener; /** * Interface for shake gesture. */ public interface OnShakeListener { /** * Called when shake gesture is detected. */ void onShake(); } public void setOnShakeListener(OnShakeListener listener) { shakeListener = listener; } @SuppressWarnings("deprecation") @Override public void onSensorChanged(SensorEvent se) { // get sensor data float x = se.values[SensorManager.DATA_X]; float y = se.values[SensorManager.DATA_Y]; float z = se.values[SensorManager.DATA_Z]; // calculate movement float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ); if (totalMovement > MIN_FORCE) { // get time long now = System.currentTimeMillis(); // store first movement time if (firstDirectionChangeTime == 0) { firstDirectionChangeTime = now; lastDirectionChangeTime = now; } // check if the last movement was not long ago long lastChangeWasAgo = now - lastDirectionChangeTime; if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE) { // store movement data lastDirectionChangeTime = now; directionChangeCount++; // store last sensor data lastX = x; lastY = y; lastZ = z; // check how many movements are so far if (directionChangeCount >= MIN_DIRECTION_CHANGE) { // check total duration long totalDuration = now - firstDirectionChangeTime; if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE) { shakeListener.onShake(); resetShakeParameters(); } } } else { resetShakeParameters(); } } } /** * Resets the shake parameters to their default values. */ private void resetShakeParameters() { firstDirectionChangeTime = 0; directionChangeCount = 0; lastDirectionChangeTime = 0; lastX = 0; lastY = 0; lastZ = 0; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }