diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java b/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java index 30116b7..c66b454 100644 --- a/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java @@ -71,6 +71,8 @@ public class HistoryContentFragment extends FragmentBase { TextView tvSmallRemain; @BindView(R.id.tv_stepGoal) TextView tvGoal; + @BindView(R.id.tv_stepRemain) + TextView tv_stepRemain; @BindView(R.id.tv_caloConsumned) TextView tvCaloConsumned; @@ -264,12 +266,12 @@ public class HistoryContentFragment extends FragmentBase { int status = jsonObject.optInt("status"); if (status == 1) { JSONObject jsonObject1 = jsonObject.optJSONObject("result"); - JSONObject jsonMod1 = jsonObject1.getJSONObject("mode_1"); - JSONObject jsonMod2 = jsonObject1.getJSONObject("mode_2"); - JSONObject jsonMod3 = jsonObject1.getJSONObject("mode_3"); - addDataModWalking(jsonMod1); - addDataModRunning(jsonMod2); - addDataModBike(jsonMod3); + JSONObject jsonMod1 = jsonObject1.optJSONObject("mode_1"); + JSONObject jsonMod2 = jsonObject1.optJSONObject("mode_2"); + JSONObject jsonMod3 = jsonObject1.optJSONObject("mode_3"); + if (jsonMod1 != null)addDataModWalking(jsonMod1); + if (jsonMod2 != null)addDataModRunning(jsonMod2); + if (jsonMod3 != null)addDataModBike(jsonMod3); } } catch (JSONException e) { @@ -295,6 +297,7 @@ public class HistoryContentFragment extends FragmentBase { tvGoal.setText(getResources().getString(R.string.step_unit, mDataCurrent.getTaget())); tvStep.setText(getResources().getString(R.string.step_unit, mDataCurrent.getSteps())); tvSmallRemain.setText(getResources().getString(R.string.step_unit_1, mDataCurrent.getStepRemain())); + tv_stepRemain.setText(mDataCurrent.getStepRemain() + getResources().getString(R.string.step)); tvRemain.setText(getResources().getString(R.string.step_unit, mDataCurrent.getStepRemain())); tvRateDone.setText(getResources().getString(R.string.percent_unit, Utils.convert2String2Decimal(mDataCurrent.getCompletePercent()))); tvCaloConsumned.setText(getResources().getString(R.string.kcal_unit, Utils.convert2String2Decimal(mDataCurrent.getKcal()))); diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java b/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java index 31f10ad..ba16e34 100644 --- a/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java @@ -235,9 +235,9 @@ public class HistoryDetailFragment extends FragmentBase { int status = jsonObject.optInt("status"); if (status == 1) { JSONObject jsonObject1 = jsonObject.optJSONObject("result"); - JSONObject jsonMod1 = jsonObject1.getJSONObject("mode_1"); - JSONObject jsonMod2 = jsonObject1.getJSONObject("mode_2"); - JSONObject jsonMod3 = jsonObject1.getJSONObject("mode_3"); + JSONObject jsonMod1 = jsonObject1.optJSONObject("mode_1"); + JSONObject jsonMod2 = jsonObject1.optJSONObject("mode_2"); + JSONObject jsonMod3 = jsonObject1.optJSONObject("mode_3"); //addDataModWalking(jsonMod1); //addDataModRunning(jsonMod2); //addDataModBike(jsonMod3); diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java b/app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java index fb52453..4038402 100644 --- a/app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java @@ -23,6 +23,7 @@ import android.widget.Toast; import com.dinhcv.lifelogpedometer.R; import com.dinhcv.lifelogpedometer.interfaces.LLAPIManagerListener; +import com.dinhcv.lifelogpedometer.interfaces.StepListener; import com.dinhcv.lifelogpedometer.model.StepModel; import com.dinhcv.lifelogpedometer.model.structure.top.StepItemInfo; import com.dinhcv.lifelogpedometer.model.structure.top.TopInfo; @@ -31,6 +32,7 @@ import com.dinhcv.lifelogpedometer.portal.LLAPIManager; import com.dinhcv.lifelogpedometer.utils.Const; import com.dinhcv.lifelogpedometer.utils.DayAxisValueFormatter; import com.dinhcv.lifelogpedometer.utils.Debug; +import com.dinhcv.lifelogpedometer.utils.SimpleStepDetector; import com.dinhcv.lifelogpedometer.utils.Utils; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -58,7 +60,7 @@ import java.util.Locale; import static com.github.mikephil.charting.utils.ColorTemplate.rgb; -public class TopTodayFragment extends FragmentBase implements SettingFragmentPresenter, SensorEventListener { +public class TopTodayFragment extends FragmentBase implements SettingFragmentPresenter, SensorEventListener, StepListener { private TextView stepsView; private TextView tvStepGoal; @@ -108,6 +110,9 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre private String[] mParties; private Integer[] mStep; private ProgressDialog progress; + private boolean isAccelo = false; + private boolean isBusy = false; + private SimpleStepDetector simpleStepDetector; private TopFragment mTopFragment; public void setRootFragment(TopFragment frag) { @@ -118,6 +123,7 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); + } @Override @@ -127,6 +133,9 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre mContext = getActivity(); sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); + simpleStepDetector = new SimpleStepDetector(); + simpleStepDetector.registerListener(this); + initView(v); // slice for the steps taken today @@ -481,6 +490,8 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre Date date = mCalendar.getTime(); tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date)); mAnaDate = date; + + getTopPage(mAnaDate, stepType); } }); @@ -493,6 +504,8 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre Date date = mCalendar.getTime(); tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date)); mAnaDate = date; + + getTopPage(mAnaDate, stepType); } }); @@ -552,6 +565,8 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre private void updateUI(){ + creatLogStep(); + Debug.normal("Step total================ "+ stepTotal); int stepRemain = stepGoal - stepTotal; double percentDone = stepTotal *100.0 / stepGoal; @@ -590,25 +605,36 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre super.onResume(); activityRunning = true; Debug.normal("Today: "+ "Onresume "); + Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); - if (countSensor != null) { - Debug.normal("Today: "+ "countSensor not null "); - sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI); - } else { - Debug.normal("Today: "+ "countSensor is null "); - Toast.makeText(mContext, getResources().getString(R.string.sensor_available), Toast.LENGTH_SHORT).show(); + if (countSensor == null) { + isAccelo = true; + countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } + if (countSensor != null) { + Debug.normal("Today: " + "countSensor not null "); + sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI); + } else { + Debug.normal("Today: " + "countSensor is null "); + Toast.makeText(mContext, getResources().getString(R.string.sensor_available), Toast.LENGTH_SHORT).show(); + } + } @Override public void onSensorChanged(SensorEvent event) { - Debug.normal("Sensor count step active"); + //Debug.normal("Sensor count step active"); if (activityRunning){ - stepCount = (int) event.values[0]; - Debug.normal("Step change: "+ stepCount); - stepTotal++; - // update UI - updateUI(); + if (isAccelo) { + simpleStepDetector.updateAccel( + event.timestamp, event.values[0], event.values[1], event.values[2]); + }else { + stepCount = (int) event.values[0]; + Debug.normal("Step change: " + stepCount); + stepTotal++; + // update UI + updateUI(); + } } } @@ -622,12 +648,11 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre super.onPause(); activityRunning = false; Debug.normal("Start create log"); - mToDate = new Date(); if (sensorManager != null) { sensorManager.unregisterListener(this); } // create log step - creatLogStep(); + //creatLogStep(); } @Override @@ -637,25 +662,38 @@ public class TopTodayFragment extends FragmentBase implements SettingFragmentPre private void creatLogStep(){ Debug.normal("Today: "+ "Create log "+ stepCount); + mToDate = new Date(); ApiServices.createLog(stepType, stepCount, mFromDate, mToDate, new LLAPIManagerListener() { @Override public void onError(Error error) { + isBusy = false; Debug.error("Get data history error"); } @Override public void onSuccess(String json) { + isBusy = false; Debug.error("Get data history success"); } @Override public void onSuccess(JSONObject object) { + isBusy = false; Debug.error("Get data history success"); } }); } - + @Override + public void step(long timeNs) { + if (!isBusy) { + isBusy = true; + stepCount = 1; + stepTotal++; + // update UI + updateUI(); + } + } } diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java b/app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java new file mode 100644 index 0000000..72be7a9 --- /dev/null +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java @@ -0,0 +1,9 @@ +package com.dinhcv.lifelogpedometer.interfaces; + +/** + * Created by Administrator on 08/01/2018. + */ + +public interface StepListener { + public void step(long timeNs); +} diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java b/app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java index 223c81c..28cdf01 100644 --- a/app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java @@ -997,6 +997,7 @@ public class LLAPIManager { @Override protected void onPreExecute() { super.onPreExecute(); + } @Override @@ -1020,6 +1021,7 @@ public class LLAPIManager { = MediaType.parse("application/json"); RequestBody requestBody = RequestBody.create(JSON, jsonObject.toString()); + Debug.warn("token data: " + APIResponse.getInstance().getToken()); final Request.Builder request = new Request.Builder() .url(baseUrl) .header("User-Agent", Utils.getCustomUA()) diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java b/app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java new file mode 100644 index 0000000..0ae3e9f --- /dev/null +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java @@ -0,0 +1,51 @@ +package com.dinhcv.lifelogpedometer.utils; + +/** + * Created by Administrator on 08/01/2018. + */ + +public class SensorFusionMath { + + private SensorFusionMath() { + } + + public static float sum(float[] array) { + float retval = 0; + for (int i = 0; i < array.length; i++) { + retval += array[i]; + } + return retval; + } + + public static float[] cross(float[] arrayA, float[] arrayB) { + float[] retArray = new float[3]; + retArray[0] = arrayA[1] * arrayB[2] - arrayA[2] * arrayB[1]; + retArray[1] = arrayA[2] * arrayB[0] - arrayA[0] * arrayB[2]; + retArray[2] = arrayA[0] * arrayB[1] - arrayA[1] * arrayB[0]; + return retArray; + } + + public static float norm(float[] array) { + float retval = 0; + for (int i = 0; i < array.length; i++) { + retval += array[i] * array[i]; + } + return (float) Math.sqrt(retval); + } + + // Note: only works with 3D vectors. + public static float dot(float[] a, float[] b) { + float retval = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + return retval; + } + + public static float[] normalize(float[] a) { + float[] retval = new float[a.length]; + float norm = norm(a); + for (int i = 0; i < a.length; i++) { + retval[i] = a[i] / norm; + } + return retval; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java b/app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java new file mode 100644 index 0000000..24446e5 --- /dev/null +++ b/app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java @@ -0,0 +1,72 @@ +package com.dinhcv.lifelogpedometer.utils; + +import com.dinhcv.lifelogpedometer.interfaces.StepListener; + +/** + * Created by Administrator on 08/01/2018. + */ + +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; + } +} +