Android跌倒检测问题

时间:2018-01-20 23:26:01

标签: java android android-studio timer scheduled-tasks

我正在尝试使用android的accelerometer实现简单的跌倒检测算法。

手机的当前加速度存储在mAccel,如果检测到突然震动Timer t开始。 Timer内有两个CountDownTimers

如果用户未在最后5秒内移动,firstTimer用于注册“跌倒”,如果用户未按下按钮,secondTimer用于确认跌倒({1}}尚未实施)。

public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        mGravity = event.values.clone();

        float x = mGravity[0];
        float y = mGravity[1];
        float z = mGravity[2];
        mAccelLast = mAccelCurrent;
        mAccelCurrent = (float) Math.sqrt(x * x + y * y + z * z);
        float delta = mAccelCurrent - mAccelLast;
        mAccel = mAccel * 0.9f + delta;
        mAccel = abs(mAccel);
        textView.setText("a:"+mAccel);
        if (abs(mAccel) > 5.0f) { // Shake detection
            t();
        }
    }
}
public void t () {

    firstTimer = new CountDownTimer(5000, 1000) {  //fall registration timer

        @Override
        public void onTick(long millisUntilFinished) {
            //if there is movement before 5 seconds pass cancel the timer
            if (abs(mAccel) > 2.0f) {
                firstTimer.cancel();
                firstTimer = null;
            }
        }

        @Override
        public void onFinish() {
            toast.show();

            secondTimer = new CountDownTimer(30*1000, 1000) { //fall confirmation timer

                @Override
                public void onTick(long millisUntilFinished) {
                    textView2.setText("" + millisUntilFinished / 1000);
                }

                @Override
                public void onFinish() {
                    Toast toast = Toast.makeText(getApplicationContext(),
                                  "Fall Registered!", Toast.LENGTH_LONG);
                        toast.show();
                    }
                }.start();
            }
        }.start();
    }

主要问题是,大多数时候firstTimer被访问,由于mAccel超过2.0阈值而被取消,而它正在减速。

我尝试使用Timer.schedule()来延迟激活firstTimer,直到加速度值“休息”为止,但它无法使用它。

1 个答案:

答案 0 :(得分:0)

我创建了一个新的Timer对象mTimer,这似乎适用于每种情况。

CountDownTimer firstTimer = new CountDownTimer(5000, 1000) {  //fall registration timer

        @Override
        public void onTick(long millisUntilFinished) {
            //if there is movement before 5 seconds pass cancel the timer
            if (abs(mAccel) > 2.0f) {
                Toast toast = Toast.makeText(getApplicationContext(),
                              "Fall not Detected", Toast.LENGTH_SHORT);
                toast.show();
                firstTimer.cancel();
            }
        }

        @Override
        public void onFinish() {
            Toast toast = Toast.makeText(getApplicationContext(),
                          "Fall Detected!", Toast.LENGTH_SHORT);
            toast.show();
            secondTimer.start();
        }
    };

    CountDownTimer secondTimer = new CountDownTimer(30*1000, 1000) {
    //fall confirmation timer

        @Override
        public void onTick(long millisUntilFinished) {
            textView2.setText("" + millisUntilFinished / 1000);
        }

        @Override
        public void onFinish() {
            Toast toast = Toast.makeText(getApplicationContext(),
            "Fall Registered!", Toast.LENGTH_LONG);
            toast.show();
        }
    };


@Override
public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        mGravity = event.values.clone();
        float x = mGravity[0];
        float y = mGravity[1];
        float z = mGravity[2];
        mAccelLast = mAccelCurrent;
        mAccelCurrent = (float) Math.sqrt(x * x + y * y + z * z);
        float delta = mAccelCurrent - mAccelLast;
        mAccel = mAccel * 0.9f + delta;
        mAccel = abs(mAccel);
        textView.setText("a:"+mAccel);
        if (abs(mAccel) > 5.0f) { // Shake detection
            mTimer.schedule(new TimerTask() { 
            //start after 2 second delay to make acceleration values "rest"

                @Override
                public void run() {
                    firstTimer.start();
                }

            }, 2000);
        }
    }
}