如何实施最具成本效益的摇动探测器

时间:2015-01-27 18:15:22

标签: android android-sensors

我有一个应用程序需要在用户打开手机屏幕时检测到抖动。我找到了很多关于如何检测震动的例子。到目前为止,使用Google代码并添加重力组件,下面的示例是最有趣的。我的问题是,这段代码可以改进吗?摇动检测非常稳定,我没有误报。我最关心的是电池寿命的改善。

private static final int mMinimumForce   = 5;
private static final int mShakeFrequency = 500;
private static final int mMovesRequired  = 4;
private float[] mGravity                 = { 0.0f, 0.0f, 0.0f };
private float[] mAcceleration            = { 0.0f, 0.0f, 0.0f };
private static final int mXAxis          = 0;
private static final int mYAxis          = 1;
private static final int mZAxis          = 2;
private long mCurrentTime                = 0;
private long mLastTime                   = 0;
private int mMoveCount                   = 0;
private final float mAlpha               = 0.8f;

public void onSensorChanged(SensorEvent event)
{
        if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
        {
            return;
        }


        // Set linear acceleration
        // Gravity components of x, y, and z acceleration
        mGravity[mXAxis] = mAlpha * mGravity[mXAxis] + (1 - mAlpha) * event.values[mXAxis];
        mGravity[mYAxis] = mAlpha * mGravity[mYAxis] + (1 - mAlpha) * event.values[mYAxis];
        mGravity[mZAxis] = mAlpha * mGravity[mZAxis] + (1 - mAlpha) * event.values[mZAxis];

        // Linear acceleration of x, y, z with gravity effect removed
        mAcceleration[mXAxis] = event.values[mXAxis] - mGravity[mXAxis];
        mAcceleration[mYAxis] = event.values[mYAxis] - mGravity[mYAxis];
        mAcceleration[mZAxis] = event.values[mZAxis] - mGravity[mZAxis];


        // Set maximum linear acceleration amongst x, y, z
        float maxAcceleration = mAcceleration[mXAxis];

        if (mAcceleration[mYAxis] > maxAcceleration)
        {
            maxAcceleration = mAcceleration[mYAxis];
        }

        if (mAcceleration[mZAxis] > maxAcceleration)
        {
            maxAcceleration = mAcceleration[mZAxis];
        }


        // Process shake
        if (maxAcceleration > mMinimumForce)
        {
            Log.d(TAG, "Shake detected");

            mCurrentTime = System.currentTimeMillis();

            if (mLastTime == 0)
            {
                mLastTime = mCurrentTime;
            }

            long elapsedTime = mCurrentTime - mLastTime;

            if (elapsedTime > mShakeFrequency)
            {
                    mLastTime  = 0;
                    mMoveCount = 0;
            }
            else
            {
                mMoveCount++;

                if (mMoveCount > mMovesRequired)
                {
                    Log.d(TAG, "Shake moves detected: " + mMovesRequired);
                    // do some work here

                        mLastTime  = 0;
                        mMoveCount = 0;
                }
            }
        }
}

1 个答案:

答案 0 :(得分:1)

Google I / O文档提供了有关您所有问题的重要信息。这是一份这样的文件。 https://dl.google.com/io/2009/pres/W_0300_CodingforLife-BatteryLifeThatIs.pdf

你对浮点数学的观点是正确的。虽然你的代码在计算方面做的并不多,但是高频率地不断调用它可能会对CPU造成负担。

关于加速计使用电池的观点。虽然每个设备在功耗方面都有所不同,并且该设备不能靠近陀螺仪使用的设备,但如果在活动屏幕使用的一整天中不间断使用,它将显示出明显的差异。

我同意无论您是否看到电池使用量存在显着差异,编码达到最高标准和效率都是好的。它只是一个好公民。如果我可以再从手机中拿出30分钟,请把它给我!!!

我对您的代码的建议,这些建议实际上只是反映了Google的推荐,而且很多您已经在谈论过。

  • 以尽可能低的轮询率注册您的听众。
  • 补充点1,在代码开头有一个过滤器,根据不满足的轮询率立即返回。 (当前时间 - 最后一次)> POLL_RATE。这很重要,因为Android可能不遵守在侦听器中注册的轮询率。
  • 如果可以,请在浮点上使用整数数学。
  • 调查是否可以在使用加速度计之前首先使用更经济实惠的AlarmManager和/或其他传感器。我不知道你的情况是否可行,但值得一试。