Show RN Dev Menu after 2 rage shakes
Reviewed By: achen1 Differential Revision: D5427430 fbshipit-source-id: cac761c550ff2627f1bbbbde9e9b8d3f122bbb45
This commit is contained in:
parent
1728a866ef
commit
794dddc5bd
|
@ -24,22 +24,17 @@ import com.facebook.infer.annotation.Assertions;
|
|||
* Listens for the user shaking their phone. Allocation-less once it starts listening.
|
||||
*/
|
||||
public class ShakeDetector implements SensorEventListener {
|
||||
|
||||
//only record and consider the last MAX_SAMPLES number of data points
|
||||
private static final int MAX_SAMPLES = 40;
|
||||
//collect sensor data in this interval (nanoseconds)
|
||||
// Collect sensor data in this interval (nanoseconds)
|
||||
private static final long MIN_TIME_BETWEEN_SAMPLES_NS =
|
||||
TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS);
|
||||
//expected duration of one shake in nanoseconds
|
||||
private static final long VISIBLE_TIME_RANGE_NS =
|
||||
TimeUnit.NANOSECONDS.convert(250, TimeUnit.MILLISECONDS);
|
||||
//minimum amount of force on accelerometer sensor to constitute a shake
|
||||
private static final int MAGNITUDE_THRESHOLD = 25;
|
||||
//this percentage of data points must have at least the force of MAGNITUDE_THRESHOLD
|
||||
private static final int PERCENT_OVER_THRESHOLD_FOR_SHAKE = 60;
|
||||
//number of nanoseconds to listen for and count shakes
|
||||
// Number of nanoseconds to listen for and count shakes (nanoseconds)
|
||||
private static final float SHAKING_WINDOW_NS =
|
||||
TimeUnit.NANOSECONDS.convert(3, TimeUnit.SECONDS);
|
||||
// Required force to constitute a rage shake. Need to multiply gravity by 1.33 because a rage
|
||||
// shake in one direction should have more force than just the magnitude of free fall.
|
||||
private static final float REQUIRED_FORCE = SensorManager.GRAVITY_EARTH * 1.33f;
|
||||
|
||||
private float mAccelerationX, mAccelerationY, mAccelerationZ;
|
||||
|
||||
public static interface ShakeListener {
|
||||
void onShake();
|
||||
|
@ -49,11 +44,8 @@ public class ShakeDetector implements SensorEventListener {
|
|||
|
||||
@Nullable private SensorManager mSensorManager;
|
||||
private long mLastTimestamp;
|
||||
private int mCurrentIndex;
|
||||
private int mNumShakes;
|
||||
private long mLastShakeTimestamp;
|
||||
@Nullable private double[] mMagnitudes;
|
||||
@Nullable private long[] mTimestamps;
|
||||
//number of shakes required to trigger onShake()
|
||||
private int mMinNumShakes;
|
||||
|
||||
|
@ -75,12 +67,9 @@ public class ShakeDetector implements SensorEventListener {
|
|||
if (accelerometer != null) {
|
||||
mSensorManager = manager;
|
||||
mLastTimestamp = -1;
|
||||
mCurrentIndex = 0;
|
||||
mMagnitudes = new double[MAX_SAMPLES];
|
||||
mTimestamps = new long[MAX_SAMPLES];
|
||||
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
|
||||
mNumShakes = 0;
|
||||
mLastShakeTimestamp = 0;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,26 +83,60 @@ public class ShakeDetector implements SensorEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all variables used to keep track of number of shakes recorded.
|
||||
*/
|
||||
private void reset() {
|
||||
mNumShakes = 0;
|
||||
mAccelerationX = 0;
|
||||
mAccelerationY = 0;
|
||||
mAccelerationZ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if acceleration applied to sensor is large enough to count as a rage shake.
|
||||
*
|
||||
* @param a acceleration in x, y, or z applied to the sensor
|
||||
* @return true if the magnitude of the force exceeds the minimum required amount of force.
|
||||
* false otherwise.
|
||||
*/
|
||||
private boolean atLeastRequiredForce(float a) {
|
||||
return Math.abs(a) > REQUIRED_FORCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data about last shake
|
||||
* @param timestamp (ns) of last sensor event
|
||||
*/
|
||||
private void recordShake(long timestamp) {
|
||||
mLastShakeTimestamp = timestamp;
|
||||
mNumShakes++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent sensorEvent) {
|
||||
if (sensorEvent.timestamp - mLastTimestamp < MIN_TIME_BETWEEN_SAMPLES_NS) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assertions.assertNotNull(mTimestamps);
|
||||
Assertions.assertNotNull(mMagnitudes);
|
||||
|
||||
float ax = sensorEvent.values[0];
|
||||
float ay = sensorEvent.values[1];
|
||||
float az = sensorEvent.values[2];
|
||||
float az = sensorEvent.values[2] - SensorManager.GRAVITY_EARTH;
|
||||
|
||||
mLastTimestamp = sensorEvent.timestamp;
|
||||
mTimestamps[mCurrentIndex] = sensorEvent.timestamp;
|
||||
mMagnitudes[mCurrentIndex] = Math.sqrt(ax * ax + ay * ay + az * az);
|
||||
|
||||
if (atLeastRequiredForce(ax) && ax * mAccelerationX <= 0) {
|
||||
recordShake(sensorEvent.timestamp);
|
||||
mAccelerationX = ax;
|
||||
} else if (atLeastRequiredForce(ay) && ay * mAccelerationY <= 0) {
|
||||
recordShake(sensorEvent.timestamp);
|
||||
mAccelerationY = ay;
|
||||
} else if (atLeastRequiredForce(az) && az * mAccelerationZ <= 0) {
|
||||
recordShake(sensorEvent.timestamp);
|
||||
mAccelerationZ = az;
|
||||
}
|
||||
|
||||
maybeDispatchShake(sensorEvent.timestamp);
|
||||
|
||||
mCurrentIndex = (mCurrentIndex + 1) % MAX_SAMPLES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -121,34 +144,13 @@ public class ShakeDetector implements SensorEventListener {
|
|||
}
|
||||
|
||||
private void maybeDispatchShake(long currentTimestamp) {
|
||||
Assertions.assertNotNull(mTimestamps);
|
||||
Assertions.assertNotNull(mMagnitudes);
|
||||
if (mNumShakes >= 8 * mMinNumShakes) {
|
||||
reset();
|
||||
mShakeListener.onShake();
|
||||
}
|
||||
|
||||
int numOverThreshold = 0;
|
||||
int total = 0;
|
||||
for (int i = 0; i < MAX_SAMPLES; i++) {
|
||||
int index = (mCurrentIndex - i + MAX_SAMPLES) % MAX_SAMPLES;
|
||||
if (currentTimestamp - mTimestamps[index] < VISIBLE_TIME_RANGE_NS) {
|
||||
total++;
|
||||
if (mMagnitudes[index] >= MAGNITUDE_THRESHOLD) {
|
||||
numOverThreshold++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((double) numOverThreshold) / total > PERCENT_OVER_THRESHOLD_FOR_SHAKE / 100.0) {
|
||||
if (currentTimestamp - mLastShakeTimestamp >= VISIBLE_TIME_RANGE_NS) {
|
||||
mNumShakes++;
|
||||
}
|
||||
mLastShakeTimestamp = currentTimestamp;
|
||||
if (mNumShakes >= mMinNumShakes) {
|
||||
mNumShakes = 0;
|
||||
mLastShakeTimestamp = 0;
|
||||
mShakeListener.onShake();
|
||||
}
|
||||
}
|
||||
if (currentTimestamp - mLastShakeTimestamp > SHAKING_WINDOW_NS) {
|
||||
mNumShakes = 0;
|
||||
mLastShakeTimestamp = 0;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue