如何检测Android手机是否掉到了地上?

时间:2017-03-14 02:06:59

标签: android android-sensors android-gravity

我可以用传感器的加速度计算速度,类型是SENSOR_TYPE_ACCELEROMETER吗? 或者我可以从传感器获得类型为SENSOR_TYPE_ACCELEROMETER的加速度方向? 我见过一些博客,关于检查加速度矢量的值,以检测Android手机是否正在填充。 但是,共鸣可能是Android手机正在颤抖并且没有填充。 我的代码是:

/**
 * how often analysising the accelerometer?(Millisecond)
 */
private static final int ANALYSIS_ACCELERATION_INTERVAL = 500;
/**
 * how often checking the accelerometer?(Millisecond)
 */
private static final int CHECK_TIME_INTERVAL = 5000;
/**
 * when the sMinorMaxAccelerationInOneSecoud[0] is less than 
 * ACCELERATION_CRITICAL_VALUE[0],and the
 * sMinorMaxAccelerationInOneSecoud[1] is more than 
 * ACCELERATION_CRITICAL_VALUE[1],i think the phone dropped to the 
 * ground.
 */
private static float ACCELERATION_CRITICAL_VALUE[] = {2, 40};

/**
 * during{@link #ANALYSIS_ACCELERATION_INTERVAL},the min accelerometer  
 *  of the phone is sMinorMaxAccelerationInOneSecoud[0],the max 
 * accelerometer of the phone is saved at 
 * sMinorMaxAccelerationInOneSecoud[1].
 */
private static float sMinorMaxAccelerationInOneSecoud[] = {0, 0};

/**
 * the last time when checking the accelerometer
 */
private static long sLastCheckTime = 0;

/**
 * the last time when analysising the accelerometer
 */
private static long sLastAnalysisTime = 0;

/**
 * during {@link #CHECK_TIME_INTERVAL},is phone dropped to ground?
 */
private static boolean sIsFallDown = false;


private SensorManager mSensorManager;

public void receiveCondition() {
    // a dialog
    Intent intent = new Intent();
    intent.setClass(GlobalHolder.getApplicationContext(), PhoneDroppedDialog.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    GlobalHolder.getApplicationContext().startActivity(intent);
}

public void start() {
    mSensorManager = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
    mSensorManager.registerListener(this,
            mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION),
            SensorManager.SENSOR_DELAY_UI);
}

public void stop() {
    mSensorManager.unregisterListener(this);
    mSensorManager = null;
    sMinorMaxAccelerationInOneSecoud = new float[]{0, 0};
    sLastCheckTime = 0;
    sLastAnalysisTime = 0;
}

@Override
public void onSensorChanged(SensorEvent event) {
    int sensorType = event.sensor.getType();
    if (sensorType != Sensor.TYPE_LINEAR_ACCELERATION) {
        return;
    }
    // judge if the sMinorMaxAccelerationInOneSecoud[0] is less than 
    // ACCELERATION_CRITICAL_VALUE[0],and the
    // sMinorMaxAccelerationInOneSecoud[1] is more than 
    // ACCELERATION_CRITICAL_VALUE[1]
    analysisAcceleration(event.values);

    long currentTime = System.currentTimeMillis();
    long beta = currentTime - sLastCheckTime;
    if (Math.abs(beta) < CHECK_TIME_INTERVAL) {
        return;
    }
    // it have been more than one secound since the last check,so we need re-check if the phone have dropped to the ground.
    checkIsFallDown();

    // reset sLastCheckTime with the current time
    sLastCheckTime = currentTime;

}

private void analysisAcceleration(float[] values) {
    if (sIsFallDown) {
        // if the phone have already dropped to the ground,we return directly.
        return;
    }

    // whether the min sum vector of the accelerations on the x_axis,y_axis,zaxis is less than ACCELERATION_CRITICAL_VALUE[0]
    // and the max sum vector of the accelerations on the x_axis,y_axis,zaxis is more than ACCELERATION_CRITICAL_VALUE[1]
    if (sLastAnalysisTime == 0) {
        sLastAnalysisTime = System.currentTimeMillis();
    }

    // the sum vector of the accelerations on the x_axis,y_axis,zaxis
    float currentAcceleration = 0f;
    for (int i = 0; i < values.length; i++) {
        currentAcceleration += (values[i] * values[i]);
    }
    currentAcceleration = (float) Math.sqrt(currentAcceleration);

    if (sMinorMaxAccelerationInOneSecoud[0] == 0 || sMinorMaxAccelerationInOneSecoud[0] > currentAcceleration) {
        sMinorMaxAccelerationInOneSecoud[0] = currentAcceleration;
    }

    if (sMinorMaxAccelerationInOneSecoud[1] == 0 || sMinorMaxAccelerationInOneSecoud[1] < currentAcceleration) {
        sMinorMaxAccelerationInOneSecoud[1] = currentAcceleration;
    }

    long currentTime = System.currentTimeMillis();
    long delta = currentTime - sLastAnalysisTime;
    if (delta < ANALYSIS_ACCELERATION_INTERVAL) {
        return;
    }
    MLog.d(TAG, "during ANALYSIS_ACCELERATION_INTERVAL, the min value is " + sMinorMaxAccelerationInOneSecoud[0] + ", the max value is " + sMinorMaxAccelerationInOneSecoud[1]);
    boolean isLessPre = sMinorMaxAccelerationInOneSecoud[0] < ACCELERATION_CRITICAL_VALUE[0];
    boolean isMoreNext = sMinorMaxAccelerationInOneSecoud[1] > ACCELERATION_CRITICAL_VALUE[1];
    sIsFallDown = isLessPre && isMoreNext;
    sLastAnalysisTime = currentTime;
    sMinorMaxAccelerationInOneSecoud = new float[]{0, 0};
}

private void checkIsFallDown() {
    if (sIsFallDown) {
        // the phone have dropped
        receiveCondition();
        MLog.d(TAG, "call the receiveCondition method.");
        sMinorMaxAccelerationInOneSecoud = new float[]{0, 0};
        sIsFallDown = false;
    }
}
有人有更好的主意吗?谢谢!

0 个答案:

没有答案