Step Detector and Step Counter

计步器的实现 描述 android计步器的实现,自定义的一个弧形进度条,记步通过手机的传感器来实现,也就是说不支持传感器的机子(应该很老的了吧)就没有效果。看看效果图: 这里写图片描述这里写图片描述 自定义View public class StepView extends View { /** * 圆弧的宽度 */ private float borderWidth = dipToPx(10); /** * 画步数的数值的字体大小 */ private float numberTextSize = 0; /** * 步数 */ private String stepNumber = "0"; /** * 开始绘制圆弧的角度 */ private float startAngle = 125; /** * 终点对应的角度和起始点对应的角度的夹角 */ private float angleLength = 290; /** * 所要绘制的当前步数的蓝色圆弧终点到起点的夹角 */ private float currentAngleLength = 0; /** * 动画时长 */ private int animationLength = 3000; /** * 当前运动类型 */ private String type = "Riding"; /** * 当前活跃等级 */ private String level = "等级:轻度活跃"; /** * 步数上方文字 */ private String today = "今日步数"; /** * 单位km是否显示 */ private String unit = "Km"; public StepView(Context context) { super(context); } public StepView(Context context, AttributeSet attrs) { super(context, attrs); } public StepView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /**中心点的x坐标*/ float centerX = (getWidth()) / 2; /**指定圆弧的外轮廓矩形区域*/ RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth); /**【第一步】绘制整体的灰色圆弧*/ drawArcYellow(canvas, rectF); /**【第二步】绘制当前进度的蓝色圆弧*/ drawArcRed(canvas, rectF); /**【第三步】绘制当前进度的白色数字*/ drawTextNumber(canvas, centerX); /**【第四步】绘制"本次步数"的灰色文字*/ drawTextStepString(canvas, centerX); /**【第五步】绘制当前记步类型*/ drawTextType(canvas, centerX); /**【第六步】绘制当前等级类型*/ drawTextLevel(canvas, centerX); /**【第七步】绘制骑行距离单位*/ drawTextUnit(canvas, centerX); } /** * 1.绘制总步数的灰色圆弧 * * @param canvas 画笔 * @param rectF 参考的矩形 */ private void drawArcYellow(Canvas canvas, RectF rectF) { Paint paint = new Paint(); /** 默认画笔颜色,灰色 */ paint.setColor(getResources().getColor(R.color.near_black)); /** 结合处为圆弧*/ paint.setStrokeJoin(Paint.Join.MITER); /** 设置画笔的样式 Paint.Cap.Round ,Cap.SQUARE等分别为圆形、方形*/ paint.setStrokeCap(Paint.Cap.BUTT); /** 设置画笔的填充样式 Paint.Style.FILL :填充内部;Paint.Style.FILL_AND_STROKE :填充内部和描边; Paint.Style.STROKE :仅描边*/ paint.setStyle(Paint.Style.STROKE); float[] floats = {4,16,4,16}; paint.setPathEffect(new DashPathEffect(floats, 0)); /**抗锯齿功能*/ paint.setAntiAlias(true); /**设置画笔宽度*/ paint.setStrokeWidth(borderWidth); /**绘制圆弧的方法 * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧, 参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧, 参数二是起始角(度)在电弧的开始,圆弧起始角度,单位为度。 参数三圆弧扫过的角度,顺时针方向,单位为度,从右中间开始为零度。 参数四是如果这是true(真)的话,在绘制圆弧时将圆心包括在内,通常用来绘制扇形;如果它是false(假)这将是一个弧线, 参数五是Paint对象; */ canvas.drawArc(rectF, startAngle, angleLength, false, paint); } /** * 2.绘制当前步数的蓝色圆弧 */ private void drawArcRed(Canvas canvas, RectF rectF) { Paint paintCurrent = new Paint(); paintCurrent.setStrokeJoin(Paint.Join.MITER); paintCurrent.setStrokeCap(Paint.Cap.BUTT);//圆角弧度 paintCurrent.setStyle(Paint.Style.STROKE);//设置填充样式 paintCurrent.setAntiAlias(true);//抗锯齿功能 paintCurrent.setStrokeWidth(borderWidth);//设置画笔宽度 paintCurrent.setColor(getResources().getColor(R.color.colorPrimary));//设置画笔颜色 float[] floats = {4,16,4,16}; paintCurrent.setPathEffect(new DashPathEffect(floats, 0)); canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent); } /** * 3.圆环中心的步数 */ private void drawTextNumber(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//抗锯齿功能 vTextPaint.setTextSize(numberTextSize); Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//字体风格 vTextPaint.setColor(getResources().getColor(R.color.white)); Rect bounds_Number = new Rect(); vTextPaint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); canvas.drawText(stepNumber, centerX, getHeight() / 2 + bounds_Number.height() / 2, vTextPaint); } /** * 4.圆环中心[本次步数]的文字 */ private void drawTextStepString(Canvas canvas, float centerX) { Paint vTextPaint = new Paint(); vTextPaint.setTextSize(dipToPx(16)); vTextPaint.setTextAlign(Paint.Align.CENTER); vTextPaint.setAntiAlias(true);//抗锯齿功能 vTextPaint.setColor(getResources().getColor(R.color.gray)); Rect bounds = new Rect(); vTextPaint.getTextBounds(today, 0, today.length(), bounds); canvas.drawText(today, centerX, getHeight() / 2 + bounds.height() - 2 * getFontHeight(numberTextSize), vTextPaint); } /** * 5.圆环中下[Walking]等文字 */ private void drawTextType(Canvas canvas, float centerX) { Paint mTypePaint = new Paint(); mTypePaint.setTextSize(dipToPx(22)); mTypePaint.setTextAlign(Paint.Align.CENTER); mTypePaint.setAntiAlias(true); mTypePaint.setColor(getResources().getColor(R.color.text_blue)); Rect bounds = new Rect(); mTypePaint.getTextBounds(type, 0, type.length(), bounds); canvas.drawText(type, centerX, getHeight() / 2 + 2 * bounds.height() + getFontHeight(numberTextSize), mTypePaint); } /** * 6.绘制圆环下方等级 */ private void drawTextLevel(Canvas canvas, float centerX) { Paint mLevelPaint = new Paint(); mLevelPaint.setTextSize(dipToPx(12)); mLevelPaint.setTextAlign(Paint.Align.CENTER); mLevelPaint.setAntiAlias(true); mLevelPaint.setColor(getResources().getColor(R.color.input_hint_gray)); Rect bounds = new Rect(); mLevelPaint.getTextBounds(level, 0, level.length(), bounds); canvas.drawText(level, centerX, getHeight() / 2 + 2 * bounds.height() + 2 * getFontHeight(numberTextSize), mLevelPaint); } /** * 7.绘制骑行单位km */ private void drawTextUnit(Canvas canvas, float centerX) { Paint mUnitPaint = new Paint(); mUnitPaint.setTextSize(dipToPx(16)); mUnitPaint.setTextAlign(Paint.Align.CENTER); mUnitPaint.setAntiAlias(true); mUnitPaint.setColor(getResources().getColor(R.color.input_hint_gray)); Rect bounds = new Rect(); mUnitPaint.getTextBounds(unit, 0, unit.length(), bounds); canvas.drawText(unit, centerX+ stepNumber.length()*80, getHeight() / 2 + bounds.height() * 3 / 2, mUnitPaint); } /** * 获取当前步数的数字的高度 * * @param fontSize 字体大小 * @return 字体高度 */ public int getFontHeight(float fontSize) { Paint paint = new Paint(); paint.setTextSize(fontSize); Rect bounds_Number = new Rect(); paint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number); return bounds_Number.height(); } /** * dip 转换成px * * @param dip * @return */ private int dipToPx(float dip) { float density = getContext().getResources().getDisplayMetrics().density; return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1)); } /** * 所走的步数进度 * @param totalStepNum 设置的步数 * @param currentCounts 所走步数 */ public void setCurrentCount(int totalStepNum, int currentCounts) { /**如果当前走的步数超过总步数则圆弧还是270度,不能成为园*/ if (currentCounts > totalStepNum) { currentCounts = totalStepNum; } /**上次所走步数占用总共步数的百分比*/ float scalePrevious = (float) Integer.valueOf(stepNumber) / totalStepNum; /**换算成弧度最后要到达的角度的长度-->弧长*/ float previousAngleLength = scalePrevious * angleLength; /**所走步数占用总共步数的百分比*/ float scale = (float) currentCounts / totalStepNum; /**换算成弧度最后要到达的角度的长度-->弧长*/ float currentAngleLength = scale * angleLength; /**开始执行动画*/ setAnimation(previousAngleLength, currentAngleLength, animationLength); stepNumber = String.valueOf(currentCounts); setTextSize(currentCounts); } /** * 设置各个参数 */ public void setParams(String today, String unit, String type, String level) { this.today = today; this.unit = unit; this.type = type; this.level = level; } /** * 为进度设置动画 * ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的, * 而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。 * 它的内部使用一种时间循环的机制来计算值与值之间的动画过渡, * 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长, * 那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。 * * @param start 初始值 * @param current 结束值 * @param length 动画时长 */ private void setAnimation(float start, float current, int length) { ValueAnimator progressAnimator = ValueAnimator.ofFloat(start, current); progressAnimator.setDuration(length); progressAnimator.setTarget(currentAngleLength); progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { /**每次在初始值和结束值之间产生的一个平滑过渡的值,逐步去更新进度*/ currentAngleLength = (float) animation.getAnimatedValue(); invalidate(); } }); progressAnimator.start(); } /** * 设置文本大小,防止步数特别大之后放不下,将字体大小动态设置 * * @param num */ public void setTextSize(int num) { String s = String.valueOf(num); int length = s.length(); if (length 4 && length 6 && length 8) { numberTextSize = dipToPx(25); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 整个View的代码逻辑还是比较清晰的,自定义的view会首先调用onDraw()方法,获取了整个布局的中心和轮廓,然后开始七步分别绘制控件,这就是大家可以发挥的部分了,想怎么设计怎么设计。 第一步着重看一下,这个虚线的实现: float[] floats = {4,16,4,16}; paint.setPathEffect(new DashPathEffect(floats, 0)); 1 2 floats的四个参数意思是{画宽度,间隔宽度,画宽度,间隔宽度},这里的floats是数组也就是说你可以把每一个宽度和间隔都写出来,当然如果一样的话你可以只列出两个,系统会自动识别来延续后面的宽度和间隔。 因为注释很清楚,其他的这里就不详述了,想改啥基本都能看明白。 记步服务 public class StepService extends Service implements SensorEventListener { private String TAG = "StepService"; /** * 默认为10秒进行一次存储 */ private static int duration = 10 * 1000; /** * 传感器管理对象 */ private SensorManager sensorManager; /** * 保存记步计时器 */ private TimeCount time; /** * 当前所走的步数 */ private int CURRENT_STEP; /** * 计步传感器类型 Sensor.TYPE_STEP_COUNTER或者Sensor.TYPE_STEP_DETECTOR */ private static int stepSensorType = -1; /** * 每次第一次启动记步服务时是否从系统中获取了已有的步数记录 */ private boolean hasRecord = false; /** * 系统中获取到的已有的步数 */ private int hasStepCount = 0; /** * 上一次的步数 */ private int previousStepCount = 0; /** * IBinder对象,向Activity传递数据的桥梁 */ private StepBinder stepBinder = new StepBinder(); @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate()"); new Thread(new Runnable() { public void run() { startStepDetector(); } }).start(); startTimeCount(); } /** * 开始保存记步数据 */ private void startTimeCount() { if (time == null) { time = new TimeCount(duration, 1000); } time.start(); } /** * UI监听器对象 */ private UpdateUiCallBack mCallback; /** * 注册UI更新监听 * * @param paramICallback */ public void registerCallback(UpdateUiCallBack paramICallback) { this.mCallback = paramICallback; } @Override public IBinder onBind(Intent intent) { return stepBinder; } /** * 向Activity传递数据的纽带 */ public class StepBinder extends Binder { /** * 获取当前service对象 * * @return StepService */ public StepService getService() { return StepService.this; } } /** * 获取当前步数 * * @return */ public int getStepCount() { return CURRENT_STEP; } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } /** * 获取传感器实例 */ private void startStepDetector() { if (sensorManager != null) { sensorManager = null; } // 获取传感器管理器的实例 sensorManager = (SensorManager) this .getSystemService(SENSOR_SERVICE); //android4.4以后可以使用计步传感器 addCountStepListener(); } /** * 添加传感器监听 * 1. TYPE_STEP_COUNTER API的解释说返回从开机被激活后统计的步数,当重启手机后该数据归零, * 该传感器是一个硬件传感器所以它是低功耗的。 * 为了能持续的计步,请不要反注册事件,就算手机处于休眠状态它依然会计步。 * 当激活的时候依然会上报步数。该sensor适合在长时间的计步需求。 * * 2.TYPE_STEP_DETECTOR翻译过来就是走路检测, * API文档也确实是这样说的,该sensor只用来监监测走步,每次返回数字1.0。 * 如果需要长事件的计步请使用TYPE_STEP_COUNTER。 */ private void addCountStepListener() { Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); Sensor detectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR); if (countSensor != null) { stepSensorType = Sensor.TYPE_STEP_COUNTER; Log.v(TAG, "Sensor.TYPE_STEP_COUNTER"); sensorManager.registerListener(StepService.this, countSensor, SensorManager.SENSOR_DELAY_NORMAL); } else if (detectorSensor != null) { stepSensorType = Sensor.TYPE_STEP_DETECTOR; Log.v(TAG, "Sensor.TYPE_STEP_DETECTOR"); sensorManager.registerListener(StepService.this, detectorSensor, SensorManager.SENSOR_DELAY_NORMAL); } } /** * 传感器监听回调 * @param event */ @Override public void onSensorChanged(SensorEvent event) { if (stepSensorType == Sensor.TYPE_STEP_COUNTER) { //获取当前传感器返回的临时步数 int tempStep = (int) event.values[0]; //首次如果没有获取手机系统中已有的步数则获取一次系统中APP还未开始记步的步数 if (!hasRecord) { hasRecord = true; hasStepCount = tempStep; } else { //获取APP打开到现在的总步数=本次系统回调的总步数-APP打开之前已有的步数 int thisStepCount = tempStep - hasStepCount; //本次有效步数=(APP打开后所记录的总步数-上一次APP打开后所记录的总步数) int thisStep = thisStepCount - previousStepCount; //总步数=现有的步数+本次有效步数 CURRENT_STEP += (thisStep); //记录最后一次APP打开到现在的总步数 previousStepCount = thisStepCount; } } else if (stepSensorType == Sensor.TYPE_STEP_DETECTOR) { if (event.values[0] == 1.0) { CURRENT_STEP++; } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } /** * 保存记步数据 */ class TimeCount extends CountDownTimer { public TimeCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onFinish() { // 如果计时器正常结束,则开始计步 time.cancel(); mCallback.updateUi(CURRENT_STEP); startTimeCount(); } @Override public void onTick(long millisUntilFinished) { } } @Override public void onDestroy() { super.onDestroy(); //取消前台进程 stopForeground(true); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 因为记步是在后台进行的,开启之后我们可以干其他事情,所以采用服务的方式,而我们需要获取记步的数据,所以要通过绑定的方式来注册服务,这样才能获得通信用的connection。逻辑思路是,通过计步器来获取步数,然后设置监听器来监听步数的改变,如果步数改变更新步数的变量,然后开启一个计时器来定时去记录,设置回调参数来返回步数。回调接口只有一个方法: public interface UpdateUiCallBack { /** * 更新UI步数 * * @param stepCount 步数 */ void updateUi(int stepCount); } 1 2 3 4 5 6 7 8 当然别忘了在AndroidManifest.xml中注册Service: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 还有记步需要用的权限: 1 2 3 调用MainActivity public class MainActivity extends AppCompatActivity { private StepView stepView; private Button button; private boolean isBind = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { stepView = (StepView) findViewById(R.id.step_walk_arv); button = (Button) findViewById(R.id.begin_btn); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { begin(); } }); } private void initData() { stepView.setParams("今日步数", "", "Walking", "等级:轻度活跃"); stepView.setCurrentCount(1000,0); } private void begin() { if (isBind == false){ //开启记步 Intent intent = new Intent(this, StepService.class); isBind = bindService(intent, conn, Context.BIND_AUTO_CREATE); startService(intent); button.setText("正在记步"); } } /** * 用于查询应用服务(application Service)的状态的一种interface, * 更详细的信息可以参考Service 和 context.bindService()中的描述, * 和许多来自系统的回调方式一样,ServiceConnection的方法都是进程的主线程中调用的。 */ ServiceConnection conn = new ServiceConnection() { /** * 在建立起于Service的连接时会调用该方法,目前Android是通过IBind机制实现与服务的连接。 * @param name 实际所连接到的Service组件名称 * @param service 服务的通信信道的IBind,可以通过Service访问对应服务 */ @Override public void onServiceConnected(ComponentName name, IBinder service) { StepService stepService = ((StepService.StepBinder) service).getService(); //设置初始化数据 stepView.setCurrentCount(1000, stepService.getStepCount()); //设置步数监听回调 stepService.registerCallback(new UpdateUiCallBack() { @Override public void updateUi(int stepCount) { stepView.setCurrentCount(1000, stepCount); } }); } /** * 当与Service之间的连接丢失的时候会调用该方法, * 这种情况经常发生在Service所在的进程崩溃或者被Kill的时候调用, * 此方法不会移除与Service的连接,当服务重新启动的时候仍然会调用 onServiceConnected()。 * @param name 丢失连接的组件名称 */ @Override public void onServiceDisconnected(ComponentName name) { } }; //服务解绑 @Override public void onDestroy() { super.onDestroy(); if (isBind) { unbindService(conn); isBind = false; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 调用也很简单,首先在布局文件中引用StepView,然后初始化,设置圆弧里面的参数,设置总步数和当前步数(开始当然为0): stepView.setParams("今日步数", "", "Walking", "等级:轻度活跃"); stepView.setCurrentCount(1000,0); 1 2 其中还设置了一个boolean值isBind区分是否已经启动服务并绑定到了activity上,以便在onDestroy()方法是解除绑定。 整个计步器的实现还是相对简单的,之前还想过要在圆弧圈外面画一个手指来指向当前的进度,不过暂时还没想通怎么实现,有兴趣的小伙伴研究之后告诉一声。 立即下载
Step Detector and Step Counter


Android 4.4 also adds platform support for two new composite sensors — step detector and step counter — that let your app track steps when the user is walking, running, or climbing stairs. These new sensors are implemented in hardware for low power consumption.


The step detector analyzes accelerometer input to recognize when the user has taken a step, then triggers an event with each step. The step counter tracks the total number of steps since the last device reboot and triggers an event with each change in the step count. Because the logic and sensor management is built into the platform and underlying hardware, you don't need to maintain your own detection algorithms in your app.


Step detector and counter sensors are available on Nexus 5, and we're working with our chipset partners to bring them to new devices as soon as possible.


I fetch the section from android official website.Last week,I got the step detector and step counter APP from one friend.He told me it is popular.Luckily get the information from Android website.


Actually,the app is a little simple,but it is widely used.It will be a great perspective for sport APP.I rightly have a good idea which is relative to sports,such as running,jogging.


I just show the outline here.A range of  people want to run,jog,but they are lazy.It is difficult to insist on.But if they search friends who have the same scenario and do it together, the exercise effectiveness will be better.They can share the effectiveness in friend's group.That's awesome.
绿色代码统计工具Blue StepCounter 绿色 代码统计 工具 Blue StepCounter 立即下载

相关推荐

Android-Step-Counter:安卓项目 3

安卓计步器 演示如何从 Android 中的计步器传感器获取当前步数的示例代码。 注意:这仅在 Nexus 5 上的 KitKat (Android 4.4) 上进行了测试,因为此 API 是在 4.4 中引入的。 执照 Copyright 2013 Mike Kelley Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed t

# Pedometer 计步器算法简介

Pedometer 计步器算法简介以Android 6.0 M 为例,它为Pedometer计步器(以下简称Pedo)提供了两颗虚拟传感器(以下用sensor):Step Counter和Step Detector.它们的定义分别是: Step Counter提供从系统启动sensor激活以后用户走动的步数。 Step Detector是当用户每走一步时就触发的事件。 事件产生的延迟应该在2秒以内。

老刘的技术专栏 6165

【AAAI 2025】轻量级特征增强新范式!FCM 模块助力小目标检测,即插即用提升模型泛化能力

本文介绍了AAAI 2025提出的轻量级特征增强新范式FCM模块,它通过显式分离并双向交互语义与空间特征,有效解决了小目标检测中特征信息失配的核心难题。该模块设计精巧,计算开销极低,能够即插即用式地嵌入YOLO等主流检测网络,显著提升模型对小目标的泛化检测能力,尤其适用于遥感、自动驾驶等对计算资源敏感的实际场景。

weixin_29056145的博客 287

android中两种计步器的区别 TYPE_STEP_DETECTOR与TYPE_STEP_COUNTER

两种计步器的区别和特点:   TYPE_STEP_DETECTOR   此传感器每次用户采取步骤触发事件。在每个用户步骤中,该传感器传递值为1.0的事件和指示步骤何时发生的时间戳。  TYPE_STEP_COUNTER   此传感器还会在每个检测到的步骤时触发事件,而是传递自该传感器首次通过应用程序注册的总累积步数。  请注意,这两个步进传感器并不总是提供相同的结果。TYPE_S

刘国栋的博客 6344

中小型微服务系统 硬件设备如何部署,QPS大概多少

作为一名合格的开发工程师,不仅仅要在前期开发阶段对业务和技术有深入了解,知道选用哪种合适的技术,业务如何拆分,还要思考后期线上环境,资源,延迟,性能等如何优化维护以及分布式系统一些线上生产的一些问题。 本篇主要针对之前了解的情况对硬件设备资源做一个简单的介绍: 首先分布式系统线上实践问题,我们应该对公司的流量,各个服务,网管,注册中心应该如何部署,部署多少台机器才合适,每台机器的配置如何,每天整体流量有多少,高峰期的请求量有多少,你的整体系统是否扛得住(注:很多公司现在直接使用K8S docker 实现

wangxuelei036的博客 1万+

HFSS的边界条件与激励方式

在电磁场理论学习中我们知道,电磁场问题的求解都归结于麦克斯韦(Maxwell)方程组的求解,在HFSS中波动方程的求解同样是由微分形式的麦克斯韦方程推导出来的。而边界条件定义了求解区域的边界以及不同物体交界处的电磁场特性,是求解麦克斯韦方程的基础。 只有在假定场矢量是单值、有界、并且沿空间连续分布的前提下,微分形式的麦克斯韦方程组才是有效的;而在求解区域的边界,不同介质的交界处和场源处,场矢量是不连续的,那么场的导数也就失去了意义。 边界条件就是定义跨越不连续边界处的电磁场特性,因此,正确地理解、定义并

ASH_GUARDIAN的博客 1万+

【Android入门到项目实战-- 9.2】—— 传感器实战使用教程(靠近黑屏和计步器)

Android传感器具体应用,实战使用教程,案例一:靠近屏幕黑屏;案例二:计步器

个人博客 2603

Materials Studio多层聚合物建模全流程:从Build Layers到LAMMPS data文件导出避坑指南

本文详细解析了使用Materials Studio构建多层聚合物模型并导出为LAMMPS data文件的全流程。重点剖析了Build Layers工具的核心逻辑、真空层处理技巧,并提供了解决导出过程中Z轴坐标偏移问题的实战方案,特别是如何利用msi2lmp工具的-shift参数进行精准校正,确保模型在LAMMPS中模拟的稳定性和准确性。

hhh00的博客 914

Android 计步传感器的实现

在Android4.4之后的版本中,Android在硬件中支持内置计步传感器。例如微信运动,支付宝运动等常用软件都是直接调用了Android中的Sensor传感器服务,从而获取到每日的步数。要完成计步传感器的调用,需要了解Sensor,SensorManager,SensorEventListener,SensorEvent四个类。SensorSensor即传感器,该类的路径为android.har

qq402164452的博客 1万+

爬取Unsplash高清壁纸:Python爬虫实战教程(最新技术)

在当今数字化时代,高清壁纸已经成为人们个性化设备的重要元素。Unsplash作为全球最知名的免费高质量图片网站,汇集了数百万张由全球摄影师贡献的高清图片。然而,Unsplash官网的下载方式需要手动操作,对于需要批量下载壁纸的用户来说效率较低。本文将带你深入探索如何使用Python爬虫技术高效爬取Unsplash高清壁纸,从基础到进阶,全面掌握图片爬取的核心技术。Unsplash成立于2013年,是一个完全免费的图片分享平台。高质量内容:所有图片均由专业摄影师上传,分辨率普遍达到4K以上免费商用。

2201_76125261的博客 936

SAP_SD模块信用管理-最早未清项判断逾期

在 SAP SD 模块的信用管理(Credit Management) 中,系统可以通过 最早未清项(Oldest Open Item) 来判断客户是否存在逾期,从而影响订单的信用检查结果。例如: 定义最大未清项目%为1%,未清天数为1天,即允许客户“逾期1天的未清应收帐款/该客户的应收帐款余额”最大比例为1%,若超过1%则将被信用冻结。的信用检查功能,用于判断客户是否有账龄过长的未清款项,并据此决定是否允许新的销售订单继续处理。然后在查看客户的信贷信息可以看到,最早的未清信息显示在系统中。

我小时候很黑的博客 863

Android硬件开发------计步传感器

在上一节《Android硬件开发------传感器介绍》中,简单介绍了Android手机的传感器类型,通过SensorManager引出传感器的使用方法,通过注册监听器,监听传感器返回的参数,本节开始就介绍几个传感器的使用。 1、计步传感器 在Sensor类中,有两个计步传感器的类型,分别是TYPE_STEP_DETECTOR和TYPE_STEP_COUNTER看似是两个类型一致的传感器类型,其实...

qq_33235287的博客 3206

数据库常见面试题(附答案)

1.事务四大特性 原子性,要么执行,要么不执行 隔离性,所有操作全部执行完以前,其它会话不能看到过程 一致性,事务前后,数据总额一致 持久性,一旦事务提交,对数据的改变就是永久的 2.数据库隔离级别,每个级别会引发什么问题,mysql默认是哪个级别 脏读:事务B读取事务A还没有提交的数据 不可重复读:两次事务读的数据不一致 幻读:事务A修改了数据,事务B也修改了数据,这时在事务A看...

csdn问鼎 46万+

Step Detector and Step Counter Sensors on Android

Step Detector and Step Counter Sensors on Android 时间2014-03-31 11:56:00Tech Droid原文http://techdroid.kbeanie.com/2014/03/step-detector-and-step-counter-sensors.html Android Ki...

weixin_34146805的博客 168

用MATLAB计算卡方值

然后,我们计算了期望频数,即在两个分类变量独立的情况下,每个单元格的预期频数。接下来,我们使用卡方检验的公式计算了卡方值。卡方检验是一种常用的统计方法,用于确定两个分类变量之间是否存在相关性。它基于观察到的频数和期望频数之间的差异来评估分类变量之间的独立性。在MATLAB中,我们可以使用。请注意,这只是一个简单的示例代码,用于说明如何使用MATLAB计算卡方值。在实际应用中,您可能需要根据您的具体数据和研究问题进行相应的修改和调整。在上面的代码中,我们首先创建了两个分类变量。函数显示了计算得到的卡方值。

CodeNexus的博客 2658

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android Step Counter & Detector Sensor

package zhangphil.sensor; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.Sen

Zhang Phil 3061

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Android Step Counter & Detector Sensor

package zhangphil.sensor; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import androi...

weixin_34256074的博客 247

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

安卓 计步传感器

概念及原理 计步传感器介绍     AndroidKitKat has added a few more hardware sensors to it’s API list. Step Sensors areone of them, which looks very promising. Although, not a lot of phones yet havethese Step Sens

2546

android 计步功能原理,Android开发——计步功能

一、使用Android内置传感器TYPE_STEP_COUNTER和TYPE_STEP_DETECTORTYPE_STEP_COUNTER 记录开机以来的总步数,适合用于开发计步器。A sensor of this type returns the number of steps taken by the user since the last reboot while activated....

weixin_35755640的博客 1563

Android开发——计步功能

一、使用Android内置传感器TYPE_STEP_COUNTER和TYPE_STEP_DETECTOR TYPE_STEP_COUNTER 记录开机以来的总步数,适合用于开发计步器。 A sensor of this type returns the number of steps taken by the user since the last reboot while activ...

Lee_01的博客 2370

Android计步器开发实战:从传感器选择到后台保活(附完整源码解析)

本文详细解析了Android计步器开发的核心难点与实战方案。文章深入探讨了TYPE_STEP_COUNTER与TYPE_STEP_DETECTOR传感器的选择策略、后台服务保活机制(如前台服务与WorkManager结合),以及步数数据的精准持久化管理,并提供了完整的源码架构解析,帮助开发者构建稳定、低功耗的计步功能。

dropout6artist的博客 1057

Android记步(运动)应用

Android记步(运动)应用 现如今随着人们对身体健康的追求,人们开始争先恐后的运动,而本文就是利用Android技术,编写一个运动记步数的应用(如有转载,请表明作者)。 一、使用Android内置传感器 TYPE_STEP_COUNTER 和 TYPE_STEP_DETECTOR TYPE_STEP_COUNTER 记录开机以来的总步数,适合用于开发计步器。 TYPE_STEP_DETEC...

qq_42662759的博客 1961

手把手教你用Android传感器开发健康类App:计步器功能完整实现指南

本文提供了一份完整的Android计步器App开发实战指南。文章深入解析了Android计步传感器(TYPE_STEP_COUNTER与TYPE_STEP_DETECTOR)的选择策略与差异,并提供了详细的源码实现,涵盖从传感器注册、后台服务架构设计到数据持久化与UI实时更新的全流程。同时,针对不同设备兼容性、电量优化等产品级考量给出了专业建议,帮助开发者构建精准可靠的计步功能。

z4a5b6的博客 636

android 获取当前,android获取当前步数

package com.example.bushu_chuanganqi;import android.app.Activity;import android.content.Context;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventLi...

weixin_42298743的博客 641

android 计步器 开发,Android计步器开发

本文只赘述Android计步器开发里计步的原理。在Android4.4版本之后,新增了STEP_COUNTER和STEP_DECTECTORSTEP_COUNTER表示自从开机以来,你走的步数累计;STEP_DECTECTOR表示你单次有效的步数。理解了这两个含义就很容易开发这个最原始和最简单的计步器了。先在AndroidManifest.xml中添加权限:这两个权限是硬件的支持。activity...

weixin_32357285的博客 919
上一篇: usb设备
下一篇: 圣诞设计的网页
zzobin
博客等级 码龄18年 95粉丝 82原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值