Commit 790fc3bf2bb0bddf37ec9a0290bf194e8be08e34
1 parent
90cd21c2ba
Exists in
master
update: fix bug count step
Showing 7 changed files with 200 additions and 25 deletions Side-by-side Diff
- app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java
- app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java
- app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java
- app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java
- app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java
- app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java
- app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java
app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java
| ... | ... | @@ -71,6 +71,8 @@ |
| 71 | 71 | TextView tvSmallRemain; |
| 72 | 72 | @BindView(R.id.tv_stepGoal) |
| 73 | 73 | TextView tvGoal; |
| 74 | + @BindView(R.id.tv_stepRemain) | |
| 75 | + TextView tv_stepRemain; | |
| 74 | 76 | |
| 75 | 77 | @BindView(R.id.tv_caloConsumned) |
| 76 | 78 | TextView tvCaloConsumned; |
| ... | ... | @@ -264,12 +266,12 @@ |
| 264 | 266 | int status = jsonObject.optInt("status"); |
| 265 | 267 | if (status == 1) { |
| 266 | 268 | JSONObject jsonObject1 = jsonObject.optJSONObject("result"); |
| 267 | - JSONObject jsonMod1 = jsonObject1.getJSONObject("mode_1"); | |
| 268 | - JSONObject jsonMod2 = jsonObject1.getJSONObject("mode_2"); | |
| 269 | - JSONObject jsonMod3 = jsonObject1.getJSONObject("mode_3"); | |
| 270 | - addDataModWalking(jsonMod1); | |
| 271 | - addDataModRunning(jsonMod2); | |
| 272 | - addDataModBike(jsonMod3); | |
| 269 | + JSONObject jsonMod1 = jsonObject1.optJSONObject("mode_1"); | |
| 270 | + JSONObject jsonMod2 = jsonObject1.optJSONObject("mode_2"); | |
| 271 | + JSONObject jsonMod3 = jsonObject1.optJSONObject("mode_3"); | |
| 272 | + if (jsonMod1 != null)addDataModWalking(jsonMod1); | |
| 273 | + if (jsonMod2 != null)addDataModRunning(jsonMod2); | |
| 274 | + if (jsonMod3 != null)addDataModBike(jsonMod3); | |
| 273 | 275 | |
| 274 | 276 | } |
| 275 | 277 | } catch (JSONException e) { |
| ... | ... | @@ -295,6 +297,7 @@ |
| 295 | 297 | tvGoal.setText(getResources().getString(R.string.step_unit, mDataCurrent.getTaget())); |
| 296 | 298 | tvStep.setText(getResources().getString(R.string.step_unit, mDataCurrent.getSteps())); |
| 297 | 299 | tvSmallRemain.setText(getResources().getString(R.string.step_unit_1, mDataCurrent.getStepRemain())); |
| 300 | + tv_stepRemain.setText(mDataCurrent.getStepRemain() + getResources().getString(R.string.step)); | |
| 298 | 301 | tvRemain.setText(getResources().getString(R.string.step_unit, mDataCurrent.getStepRemain())); |
| 299 | 302 | tvRateDone.setText(getResources().getString(R.string.percent_unit, Utils.convert2String2Decimal(mDataCurrent.getCompletePercent()))); |
| 300 | 303 | tvCaloConsumned.setText(getResources().getString(R.string.kcal_unit, Utils.convert2String2Decimal(mDataCurrent.getKcal()))); |
app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java
| ... | ... | @@ -235,9 +235,9 @@ |
| 235 | 235 | int status = jsonObject.optInt("status"); |
| 236 | 236 | if (status == 1) { |
| 237 | 237 | JSONObject jsonObject1 = jsonObject.optJSONObject("result"); |
| 238 | - JSONObject jsonMod1 = jsonObject1.getJSONObject("mode_1"); | |
| 239 | - JSONObject jsonMod2 = jsonObject1.getJSONObject("mode_2"); | |
| 240 | - JSONObject jsonMod3 = jsonObject1.getJSONObject("mode_3"); | |
| 238 | + JSONObject jsonMod1 = jsonObject1.optJSONObject("mode_1"); | |
| 239 | + JSONObject jsonMod2 = jsonObject1.optJSONObject("mode_2"); | |
| 240 | + JSONObject jsonMod3 = jsonObject1.optJSONObject("mode_3"); | |
| 241 | 241 | //addDataModWalking(jsonMod1); |
| 242 | 242 | //addDataModRunning(jsonMod2); |
| 243 | 243 | //addDataModBike(jsonMod3); |
app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java
| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | |
| 24 | 24 | import com.dinhcv.lifelogpedometer.R; |
| 25 | 25 | import com.dinhcv.lifelogpedometer.interfaces.LLAPIManagerListener; |
| 26 | +import com.dinhcv.lifelogpedometer.interfaces.StepListener; | |
| 26 | 27 | import com.dinhcv.lifelogpedometer.model.StepModel; |
| 27 | 28 | import com.dinhcv.lifelogpedometer.model.structure.top.StepItemInfo; |
| 28 | 29 | import com.dinhcv.lifelogpedometer.model.structure.top.TopInfo; |
| ... | ... | @@ -31,6 +32,7 @@ |
| 31 | 32 | import com.dinhcv.lifelogpedometer.utils.Const; |
| 32 | 33 | import com.dinhcv.lifelogpedometer.utils.DayAxisValueFormatter; |
| 33 | 34 | import com.dinhcv.lifelogpedometer.utils.Debug; |
| 35 | +import com.dinhcv.lifelogpedometer.utils.SimpleStepDetector; | |
| 34 | 36 | import com.dinhcv.lifelogpedometer.utils.Utils; |
| 35 | 37 | import com.github.mikephil.charting.components.XAxis; |
| 36 | 38 | import com.github.mikephil.charting.components.YAxis; |
| ... | ... | @@ -58,7 +60,7 @@ |
| 58 | 60 | import static com.github.mikephil.charting.utils.ColorTemplate.rgb; |
| 59 | 61 | |
| 60 | 62 | |
| 61 | -public class TopTodayFragment extends FragmentBase implements SettingFragmentPresenter, SensorEventListener { | |
| 63 | +public class TopTodayFragment extends FragmentBase implements SettingFragmentPresenter, SensorEventListener, StepListener { | |
| 62 | 64 | |
| 63 | 65 | private TextView stepsView; |
| 64 | 66 | private TextView tvStepGoal; |
| ... | ... | @@ -108,6 +110,9 @@ |
| 108 | 110 | private String[] mParties; |
| 109 | 111 | private Integer[] mStep; |
| 110 | 112 | private ProgressDialog progress; |
| 113 | + private boolean isAccelo = false; | |
| 114 | + private boolean isBusy = false; | |
| 115 | + private SimpleStepDetector simpleStepDetector; | |
| 111 | 116 | |
| 112 | 117 | private TopFragment mTopFragment; |
| 113 | 118 | public void setRootFragment(TopFragment frag) { |
| ... | ... | @@ -118,6 +123,7 @@ |
| 118 | 123 | public void onCreate(final Bundle savedInstanceState) { |
| 119 | 124 | super.onCreate(savedInstanceState); |
| 120 | 125 | setHasOptionsMenu(true); |
| 126 | + | |
| 121 | 127 | } |
| 122 | 128 | |
| 123 | 129 | @Override |
| ... | ... | @@ -127,6 +133,9 @@ |
| 127 | 133 | mContext = getActivity(); |
| 128 | 134 | sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); |
| 129 | 135 | |
| 136 | + simpleStepDetector = new SimpleStepDetector(); | |
| 137 | + simpleStepDetector.registerListener(this); | |
| 138 | + | |
| 130 | 139 | initView(v); |
| 131 | 140 | |
| 132 | 141 | // slice for the steps taken today |
| ... | ... | @@ -481,6 +490,8 @@ |
| 481 | 490 | Date date = mCalendar.getTime(); |
| 482 | 491 | tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date)); |
| 483 | 492 | mAnaDate = date; |
| 493 | + | |
| 494 | + getTopPage(mAnaDate, stepType); | |
| 484 | 495 | } |
| 485 | 496 | }); |
| 486 | 497 | |
| ... | ... | @@ -493,6 +504,8 @@ |
| 493 | 504 | Date date = mCalendar.getTime(); |
| 494 | 505 | tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date)); |
| 495 | 506 | mAnaDate = date; |
| 507 | + | |
| 508 | + getTopPage(mAnaDate, stepType); | |
| 496 | 509 | } |
| 497 | 510 | }); |
| 498 | 511 | |
| ... | ... | @@ -552,6 +565,8 @@ |
| 552 | 565 | |
| 553 | 566 | |
| 554 | 567 | private void updateUI(){ |
| 568 | + creatLogStep(); | |
| 569 | + | |
| 555 | 570 | Debug.normal("Step total================ "+ stepTotal); |
| 556 | 571 | int stepRemain = stepGoal - stepTotal; |
| 557 | 572 | double percentDone = stepTotal *100.0 / stepGoal; |
| 558 | 573 | |
| 559 | 574 | |
| 560 | 575 | |
| 561 | 576 | |
| ... | ... | @@ -590,25 +605,36 @@ |
| 590 | 605 | super.onResume(); |
| 591 | 606 | activityRunning = true; |
| 592 | 607 | Debug.normal("Today: "+ "Onresume "); |
| 608 | + | |
| 593 | 609 | Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); |
| 594 | - if (countSensor != null) { | |
| 595 | - Debug.normal("Today: "+ "countSensor not null "); | |
| 596 | - sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI); | |
| 597 | - } else { | |
| 598 | - Debug.normal("Today: "+ "countSensor is null "); | |
| 599 | - Toast.makeText(mContext, getResources().getString(R.string.sensor_available), Toast.LENGTH_SHORT).show(); | |
| 610 | + if (countSensor == null) { | |
| 611 | + isAccelo = true; | |
| 612 | + countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); | |
| 600 | 613 | } |
| 614 | + if (countSensor != null) { | |
| 615 | + Debug.normal("Today: " + "countSensor not null "); | |
| 616 | + sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI); | |
| 617 | + } else { | |
| 618 | + Debug.normal("Today: " + "countSensor is null "); | |
| 619 | + Toast.makeText(mContext, getResources().getString(R.string.sensor_available), Toast.LENGTH_SHORT).show(); | |
| 620 | + } | |
| 621 | + | |
| 601 | 622 | } |
| 602 | 623 | |
| 603 | 624 | @Override |
| 604 | 625 | public void onSensorChanged(SensorEvent event) { |
| 605 | - Debug.normal("Sensor count step active"); | |
| 626 | + //Debug.normal("Sensor count step active"); | |
| 606 | 627 | if (activityRunning){ |
| 607 | - stepCount = (int) event.values[0]; | |
| 608 | - Debug.normal("Step change: "+ stepCount); | |
| 609 | - stepTotal++; | |
| 610 | - // update UI | |
| 611 | - updateUI(); | |
| 628 | + if (isAccelo) { | |
| 629 | + simpleStepDetector.updateAccel( | |
| 630 | + event.timestamp, event.values[0], event.values[1], event.values[2]); | |
| 631 | + }else { | |
| 632 | + stepCount = (int) event.values[0]; | |
| 633 | + Debug.normal("Step change: " + stepCount); | |
| 634 | + stepTotal++; | |
| 635 | + // update UI | |
| 636 | + updateUI(); | |
| 637 | + } | |
| 612 | 638 | } |
| 613 | 639 | } |
| 614 | 640 | |
| 615 | 641 | |
| ... | ... | @@ -622,12 +648,11 @@ |
| 622 | 648 | super.onPause(); |
| 623 | 649 | activityRunning = false; |
| 624 | 650 | Debug.normal("Start create log"); |
| 625 | - mToDate = new Date(); | |
| 626 | 651 | if (sensorManager != null) { |
| 627 | 652 | sensorManager.unregisterListener(this); |
| 628 | 653 | } |
| 629 | 654 | // create log step |
| 630 | - creatLogStep(); | |
| 655 | + //creatLogStep(); | |
| 631 | 656 | } |
| 632 | 657 | |
| 633 | 658 | @Override |
| 634 | 659 | |
| 635 | 660 | |
| 636 | 661 | |
| 637 | 662 | |
| ... | ... | @@ -637,26 +662,39 @@ |
| 637 | 662 | |
| 638 | 663 | private void creatLogStep(){ |
| 639 | 664 | Debug.normal("Today: "+ "Create log "+ stepCount); |
| 665 | + mToDate = new Date(); | |
| 640 | 666 | |
| 641 | 667 | ApiServices.createLog(stepType, stepCount, mFromDate, mToDate, new LLAPIManagerListener() { |
| 642 | 668 | @Override |
| 643 | 669 | public void onError(Error error) { |
| 670 | + isBusy = false; | |
| 644 | 671 | Debug.error("Get data history error"); |
| 645 | 672 | } |
| 646 | 673 | |
| 647 | 674 | @Override |
| 648 | 675 | public void onSuccess(String json) { |
| 676 | + isBusy = false; | |
| 649 | 677 | Debug.error("Get data history success"); |
| 650 | 678 | } |
| 651 | 679 | |
| 652 | 680 | @Override |
| 653 | 681 | public void onSuccess(JSONObject object) { |
| 682 | + isBusy = false; | |
| 654 | 683 | Debug.error("Get data history success"); |
| 655 | 684 | } |
| 656 | 685 | }); |
| 657 | 686 | } |
| 658 | 687 | |
| 659 | 688 | |
| 660 | - | |
| 689 | + @Override | |
| 690 | + public void step(long timeNs) { | |
| 691 | + if (!isBusy) { | |
| 692 | + isBusy = true; | |
| 693 | + stepCount = 1; | |
| 694 | + stepTotal++; | |
| 695 | + // update UI | |
| 696 | + updateUI(); | |
| 697 | + } | |
| 698 | + } | |
| 661 | 699 | } |
app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java
app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java
| ... | ... | @@ -997,6 +997,7 @@ |
| 997 | 997 | @Override |
| 998 | 998 | protected void onPreExecute() { |
| 999 | 999 | super.onPreExecute(); |
| 1000 | + | |
| 1000 | 1001 | } |
| 1001 | 1002 | |
| 1002 | 1003 | @Override |
| ... | ... | @@ -1020,6 +1021,7 @@ |
| 1020 | 1021 | = MediaType.parse("application/json"); |
| 1021 | 1022 | RequestBody requestBody = RequestBody.create(JSON, jsonObject.toString()); |
| 1022 | 1023 | |
| 1024 | + Debug.warn("token data: " + APIResponse.getInstance().getToken()); | |
| 1023 | 1025 | final Request.Builder request = new Request.Builder() |
| 1024 | 1026 | .url(baseUrl) |
| 1025 | 1027 | .header("User-Agent", Utils.getCustomUA()) |
app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java
| 1 | +package com.dinhcv.lifelogpedometer.utils; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by Administrator on 08/01/2018. | |
| 5 | + */ | |
| 6 | + | |
| 7 | +public class SensorFusionMath { | |
| 8 | + | |
| 9 | + private SensorFusionMath() { | |
| 10 | + } | |
| 11 | + | |
| 12 | + public static float sum(float[] array) { | |
| 13 | + float retval = 0; | |
| 14 | + for (int i = 0; i < array.length; i++) { | |
| 15 | + retval += array[i]; | |
| 16 | + } | |
| 17 | + return retval; | |
| 18 | + } | |
| 19 | + | |
| 20 | + public static float[] cross(float[] arrayA, float[] arrayB) { | |
| 21 | + float[] retArray = new float[3]; | |
| 22 | + retArray[0] = arrayA[1] * arrayB[2] - arrayA[2] * arrayB[1]; | |
| 23 | + retArray[1] = arrayA[2] * arrayB[0] - arrayA[0] * arrayB[2]; | |
| 24 | + retArray[2] = arrayA[0] * arrayB[1] - arrayA[1] * arrayB[0]; | |
| 25 | + return retArray; | |
| 26 | + } | |
| 27 | + | |
| 28 | + public static float norm(float[] array) { | |
| 29 | + float retval = 0; | |
| 30 | + for (int i = 0; i < array.length; i++) { | |
| 31 | + retval += array[i] * array[i]; | |
| 32 | + } | |
| 33 | + return (float) Math.sqrt(retval); | |
| 34 | + } | |
| 35 | + | |
| 36 | + // Note: only works with 3D vectors. | |
| 37 | + public static float dot(float[] a, float[] b) { | |
| 38 | + float retval = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
| 39 | + return retval; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public static float[] normalize(float[] a) { | |
| 43 | + float[] retval = new float[a.length]; | |
| 44 | + float norm = norm(a); | |
| 45 | + for (int i = 0; i < a.length; i++) { | |
| 46 | + retval[i] = a[i] / norm; | |
| 47 | + } | |
| 48 | + return retval; | |
| 49 | + } | |
| 50 | + | |
| 51 | +} |
app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java
| 1 | +package com.dinhcv.lifelogpedometer.utils; | |
| 2 | + | |
| 3 | +import com.dinhcv.lifelogpedometer.interfaces.StepListener; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by Administrator on 08/01/2018. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +public class SimpleStepDetector { | |
| 10 | + private static final int ACCEL_RING_SIZE = 50; | |
| 11 | + private static final int VEL_RING_SIZE = 10; | |
| 12 | + private static final float STEP_THRESHOLD = 4f; | |
| 13 | + private static final int STEP_DELAY_NS = 250000000; | |
| 14 | + | |
| 15 | + private int accelRingCounter = 0; | |
| 16 | + private float[] accelRingX = new float[ACCEL_RING_SIZE]; | |
| 17 | + private float[] accelRingY = new float[ACCEL_RING_SIZE]; | |
| 18 | + private float[] accelRingZ = new float[ACCEL_RING_SIZE]; | |
| 19 | + private int velRingCounter = 0; | |
| 20 | + private float[] velRing = new float[VEL_RING_SIZE]; | |
| 21 | + private long lastStepTimeNs = 0; | |
| 22 | + private float oldVelocityEstimate = 0; | |
| 23 | + | |
| 24 | + private StepListener listener; | |
| 25 | + | |
| 26 | + public void registerListener(StepListener listener) { | |
| 27 | + this.listener = listener; | |
| 28 | + } | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * Accepts updates from the accelerometer. | |
| 32 | + */ | |
| 33 | + public void updateAccel(long timeNs, float x, float y, float z) { | |
| 34 | + float[] currentAccel = new float[3]; | |
| 35 | + currentAccel[0] = x; | |
| 36 | + currentAccel[1] = y; | |
| 37 | + currentAccel[2] = z; | |
| 38 | + | |
| 39 | + // First step is to update our guess of where the global z vector is. | |
| 40 | + accelRingCounter++; | |
| 41 | + accelRingX[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[0]; | |
| 42 | + accelRingY[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[1]; | |
| 43 | + accelRingZ[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[2]; | |
| 44 | + | |
| 45 | + float[] worldZ = new float[3]; | |
| 46 | + worldZ[0] = SensorFusionMath.sum(accelRingX) / Math.min(accelRingCounter, ACCEL_RING_SIZE); | |
| 47 | + worldZ[1] = SensorFusionMath.sum(accelRingY) / Math.min(accelRingCounter, ACCEL_RING_SIZE); | |
| 48 | + worldZ[2] = SensorFusionMath.sum(accelRingZ) / Math.min(accelRingCounter, ACCEL_RING_SIZE); | |
| 49 | + | |
| 50 | + float normalization_factor = SensorFusionMath.norm(worldZ); | |
| 51 | + | |
| 52 | + worldZ[0] = worldZ[0] / normalization_factor; | |
| 53 | + worldZ[1] = worldZ[1] / normalization_factor; | |
| 54 | + worldZ[2] = worldZ[2] / normalization_factor; | |
| 55 | + | |
| 56 | + // Next step is to figure out the component of the current acceleration | |
| 57 | + // in the direction of world_z and subtract gravity's contribution | |
| 58 | + float currentZ = SensorFusionMath.dot(worldZ, currentAccel) - normalization_factor; | |
| 59 | + velRingCounter++; | |
| 60 | + velRing[velRingCounter % VEL_RING_SIZE] = currentZ; | |
| 61 | + | |
| 62 | + float velocityEstimate = SensorFusionMath.sum(velRing); | |
| 63 | + | |
| 64 | + if (velocityEstimate > STEP_THRESHOLD && oldVelocityEstimate <= STEP_THRESHOLD | |
| 65 | + && (timeNs - lastStepTimeNs > STEP_DELAY_NS)) { | |
| 66 | + listener.step(timeNs); | |
| 67 | + lastStepTimeNs = timeNs; | |
| 68 | + } | |
| 69 | + oldVelocityEstimate = velocityEstimate; | |
| 70 | + } | |
| 71 | +} |