首页 > 解决方案 > 重新打开应用程序并重新启动计数器(摇晃手机)时,停止计步器/加速度计重置为 0?

问题描述

我前段时间问过这个问题(防止步骤计数器在应用关闭时返回 0?)但是我现在已经将每日步骤存储到了 Firebase,我面临着一个不同的问题。我遇到的问题是,当应用程序重新打开时,应用程序会显示数据库中的步数,但是一旦我摇动手机,计数器仍会重置为 0 .. 我不确定它是否与step方法有关,或updateAccel方法,我试过移动一些东西,但不幸的是没有任何运气..

这是我的计步器活动:

public class ActivityFragment extends Fragment implements SensorEventListener, StepListener {

private TextView textView;
private TextView stepsTotalMax;
private SimpleStepDetector simpleStepDetector;
private SensorManager sensorManager;
private Sensor accel;
private static final String TEXT_NUM_STEPS = "";
private int numSteps;
private ProgressBar progressBar;
String intentActivity;
String uid;
Dog dog;

private FirebaseAuth firebaseAuth;
private FirebaseUser currentUser;
DatabaseReference databaseReference;

DateTimeFormatter dtf;
LocalDateTime now;
String dateString;

@RequiresApi(api = Build.VERSION_CODES.O)
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_activity, container, false);

    intentActivity = getActivity().getIntent().getStringExtra("name");

    // ------------- firebase --------------
    firebaseAuth = FirebaseAuth.getInstance();
    currentUser = firebaseAuth.getCurrentUser();
    uid = currentUser.getUid();
    databaseReference = FirebaseDatabase.getInstance().getReference("user").child(uid).child("dogs").child(intentActivity);
    // -------------------------------------

    dtf = DateTimeFormatter.ofPattern("ddMMyyyy");
    now = LocalDateTime.now();
    dateString = dtf.format(now);

    // Get an instance of the SensorManager
    sensorManager = (SensorManager) getActivity().getSystemService(SENSOR_SERVICE);
    accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

    textView = view.findViewById(R.id.textViewStepCounter);
    progressBar = view.findViewById(R.id.stepsProgress);
    stepsTotalMax = view.findViewById(R.id.stepsTotalMax);
    textView.setTextSize(30);

    getDogData();
    dog = new Dog();

    simpleStepDetector = new SimpleStepDetector();
    simpleStepDetector.registerListener(this);
    return view;


}


@Override
public void onResume() {
    super.onResume();
    textView.setText(TEXT_NUM_STEPS + numSteps);
    sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
public void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

@Override
public void onStop() {
    super.onStop();
}

@Override
public void onSensorChanged(SensorEvent event) {

    databaseReference.addValueEventListener(new ValueEventListener() {
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            String activity = dataSnapshot.child("activity goal").getValue(String.class);
            String steps = dataSnapshot.child("steps").child(dateString).getValue(String.class);

            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

                simpleStepDetector.updateAccel(
                        event.timestamp, event.values[0], event.values[1], event.values[2]);
                if (steps == null) {
                    textView.setText("0");
                } else {
                    textView.setText(steps);
                }
                progressBar.setMax(Integer.parseInt(activity)); // change this so it is dynamically pulled when user sets max value
                ObjectAnimator.ofInt(progressBar, "progress", numSteps)
                        .setDuration(300)
                        .start();
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.w("TAG", "onCancelled", databaseError.toException());
        }
    });


}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

@Override
public void step(long timeNs) {
    databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            String steps = dataSnapshot.child("steps").child(dateString).getValue(String.class);

            if (steps == null) {
                textView.setText("0");
            } else {
                textView.setText(steps);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.w("TAG", "onCancelled", databaseError.toException());
        }
    });
    numSteps++;
    textView.setText(TEXT_NUM_STEPS + numSteps);
    databaseReference.child("steps").child(dateString).setValue(String.valueOf(numSteps));
}

private void getDogData() {

    databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            String name = dataSnapshot.child("name").getValue(String.class);
            String activity = dataSnapshot.child("activity goal").getValue(String.class);
            String steps = dataSnapshot.child("steps").child(dateString).getValue(String.class);


            if (activity.isEmpty()) {
                stepsTotalMax.setText("60" + " mins");
            } else {
                stepsTotalMax.setText(activity + " mins");
            }

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.w("TAG", "onCancelled", databaseError.toException());
        }
    });

}

}

以及来自 Google 的 SimpleStepDetector

public class SimpleStepDetector {

  private static final int ACCEL_RING_SIZE = 50;
  private static final int VEL_RING_SIZE = 10;
  private static final float STEP_THRESHOLD = 4f;
  private static final int STEP_DELAY_NS = 250000000;

  private int accelRingCounter = 0;
  private float[] accelRingX = new float[ACCEL_RING_SIZE];
  private float[] accelRingY = new float[ACCEL_RING_SIZE];
  private float[] accelRingZ = new float[ACCEL_RING_SIZE];
  private int velRingCounter = 0;
  private float[] velRing = new float[VEL_RING_SIZE];
  private long lastStepTimeNs = 0;
  private float oldVelocityEstimate = 0;

  private StepListener listener;

  public void registerListener(StepListener listener) {
    this.listener = listener;
  }

  /**
   * Accepts updates from the accelerometer.
   */
  public void updateAccel(long timeNs, float x, float y, float z) {
    float[] currentAccel = new float[3];
    currentAccel[0] = x;
    currentAccel[1] = y;
    currentAccel[2] = z;

    // First step is to update our guess of where the global z vector is.
    accelRingCounter++;
    accelRingX[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[0];
    accelRingY[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[1];
    accelRingZ[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[2];

    float[] worldZ = new float[3];
    worldZ[0] = SensorFusionMath.sum(accelRingX) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
    worldZ[1] = SensorFusionMath.sum(accelRingY) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
    worldZ[2] = SensorFusionMath.sum(accelRingZ) / Math.min(accelRingCounter, ACCEL_RING_SIZE);

    float normalization_factor = SensorFusionMath.norm(worldZ);

    worldZ[0] = worldZ[0] / normalization_factor;
    worldZ[1] = worldZ[1] / normalization_factor;
    worldZ[2] = worldZ[2] / normalization_factor;

    // Next step is to figure out the component of the current acceleration
    // in the direction of world_z and subtract gravity's contribution
    float currentZ = SensorFusionMath.dot(worldZ, currentAccel) - normalization_factor;
    velRingCounter++;
    velRing[velRingCounter % VEL_RING_SIZE] = currentZ;

    float velocityEstimate = SensorFusionMath.sum(velRing);

    if (velocityEstimate > STEP_THRESHOLD && oldVelocityEstimate <= STEP_THRESHOLD
        && (timeNs - lastStepTimeNs > STEP_DELAY_NS)) {
      listener.step(timeNs);
      lastStepTimeNs = timeNs;
    }
    oldVelocityEstimate = velocityEstimate;
  }
}

标签: javaandroidaccelerometerandroid-sensors

解决方案


推荐阅读