上一篇见:

Android计步器的实现(1)

2.时间戳工具

public abstract class Util4Pedometer {/*** @return milliseconds since 1.1.1970 for today 0:00:00*/public static long getToday() {Calendar c = Calendar.getInstance();c.setTimeInMillis(System.currentTimeMillis());c.set(Calendar.HOUR_OF_DAY, 0);c.set(Calendar.MINUTE, 0);c.set(Calendar.SECOND, 0);c.set(Calendar.MILLISECOND, 0);return c.getTimeInMillis();}
}

3.获取当天的步数

以往的步数建议服务器获取。获取当天步数代码:
/*** 使用该方法前必须对context进行初始化*/
public class StepsCountTool {public static Context context;/*** 获得当天的步数,若步数异常重置步数* 这里返回String是因为方便往服务器提交数据时加密(如:RSA)*/public static String getTodaySteps() {if (null == context) {return "0";}int result = 0;Database db = Database.getInstance(context);long today = Util4Pedometer.getToday();// 当天步数为当天的steps数据与sensor数据之和result = db.getSteps(today) + db.getSensorSteps(today);if (0 > result) {// 说明数据异常(只有在跨天且计步器逻辑没有被触发才有可能异常,此处触发几率不大,保险起见,// 看计步器服务调用该方法的位置可理解),应该重置当前的步数db.updateSteps(today, -db.getSteps(today));db.updateSensorSteps(today, 0);result = 0;}return result + "";}
}

4.计步器服务的实现

计步器要一直在后台运行就使用到了Service,如果不能一直运行则某些情况会使计数偏小,关于如何保活,这是个问题,这里只尽可能的使服务唤醒
(请自行解决,最后会给出源码,仅供参考)。计步服务代码:
@TargetApi(Build.VERSION_CODES.KITKAT)
public class SensorListener extends Service implements SensorEventListener {public static boolean isShutdowning = false;// 只有接收到关机广播才会置为trueprivate Database db;public static int steps = 0;private final static int MICROSECONDS_IN_ONE_MINUTE = 60000000;@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}@Overridepublic void onSensorChanged(final SensorEvent event) {// 关机时不往下执行if (isShutdowning) {return;}// 若步数异常(用户随意调整时间后,开关机等等),修复步数StepsCountTool.getTodaySteps();Sensor sensor = event.sensor;if (sensor.getType() != Sensor.TYPE_STEP_COUNTER) {return;}steps = (int) event.values[0];db = Database.getInstance(this);long today = Util4Pedometer.getToday();long yesterDay = today - 24 * 60 * 60 * 1000;int correctSensorSteps;int off = db.getOffStatus(yesterDay);if (off == 0) {// 说明昨天没有关机,得到修正值:当前计步器数据 - 上一天sensor修正值,手机异常关机,会使steps的值从0开始// 正常情况correctSensorSteps 为正correctSensorSteps = steps - db.getSensorSteps(yesterDay);if (correctSensorSteps < 0) {// 说明手机异常关机:扣电池或使用脚本关机导致关机广播没有发出,正常关机时会将所有off置为1,db.updateOffStatus(yesterDay, 1);// 异常关机后重启先保存关机前的数据db.updateSteps(today, db.getSensorSteps(today));// 再重新计算步数,这样能最大可能的接近真实值,此时steps从1开始db.updateSensorSteps(today, steps);} else {// 如果没有关机,跨天时一定会执行if中的代码,因为insertNewDay的sensor和steps的参数都是0,// 在第一次监听到计步器改变时,senor的值还未改变if (db.getSensorSteps(today) <= 0) {// 这里每天只更新一次sensor,更新后和sensor的和为0,跨天问题解决// steps此时为0,将sensor偏移量取反放入steps中,db.updateSteps(today, -correctSensorSteps);}db.updateSensorSteps(today, correctSensorSteps);}} else if (off == 1) {// 说明昨天关机,correctSensorSteps 就是传感器的真实值correctSensorSteps = steps;db.updateSensorSteps(today, correctSensorSteps);} else {// 计步器异常}}@Overridepublic IBinder onBind(final Intent intent) {return null;}@Overridepublic int onStartCommand(final Intent intent, int flags, int startId) {if (isShutdowning) {return START_STICKY;}db = Database.getInstance(this);// 每次启动服务都将今天的状态置为0db.updateOffStatus(Util4Pedometer.getToday(), 0);// restart service every hour to get the current step count((AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE)).set(AlarmManager.RTC, System.currentTimeMillis() + AlarmManager.INTERVAL_HOUR,PendingIntent.getService(getApplicationContext(), 2,new Intent(this, SensorListener.class),PendingIntent.FLAG_UPDATE_CURRENT));return START_STICKY;}@Overridepublic void onCreate() {super.onCreate();reRegisterSensor();}@Overridepublic void onTaskRemoved(final Intent rootIntent) {super.onTaskRemoved(rootIntent);// Restart service in 500 ms((AlarmManager) getSystemService(Context.ALARM_SERVICE)).set(AlarmManager.RTC, System.currentTimeMillis() + 500, PendingIntent.getService(this, 3, new Intent(this, SensorListener.class), 0));}@Overridepublic void onDestroy() {super.onDestroy();if (null != db) {db.close();}try {SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);sm.unregisterListener(this);} catch (Exception e) {e.printStackTrace();}reRegisterSensor();}@TargetApi(19)private void reRegisterSensor() {if (Build.VERSION.SDK_INT < 19) {return;}SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);if (null == sm) {// 无法获得传感器管理组件} else {// 获得传感器管理组件}try {sm.unregisterListener(this);} catch (Exception e) {e.printStackTrace();}if (null == sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)) {// 没有计步器} else {// 有计步器}sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),SensorManager.SENSOR_DELAY_NORMAL, 5 * MICROSECONDS_IN_ONE_MINUTE);}
}

5.手机正常关机的处理

/*** 监听到关机广播后,如下处理*/
public class ShutdownReceiver extends BroadcastReceiver {@TargetApi(Build.VERSION_CODES.KITKAT)@Overridepublic void onReceive(final Context context, final Intent intent) {// 如果没接收到关机广播直接退出等下次启动时重新初始化if (!"android.intent.action.ACTION_SHUTDOWN".equals(intent.getAction())) {return;}// if the user used a root script for shutdown, the DEVICE_SHUTDOWN// broadcast might not be send. Therefore, the app will check this// setting on the next boot and displays an error message if it's not// set to true// 然而异常关机和正常安装app无法区分,此sp暂时无用context.getSharedPreferences("pedometer", Context.MODE_PRIVATE).edit().putBoolean("correctShutdown", true).commit();// 接收到关机广播的时候SensorListener不应该再执行SensorListener.isShutdowning = true;Database db = Database.getInstance(context);long today = Util4Pedometer.getToday();long yesterDay = today - 24 * 60 * 60 * 1000;int correctSensorSteps = 0;int off = db.getOffStatus(yesterDay);if (off == 0) {// 说明昨天没有关机correctSensorSteps = SensorListener.steps - db.getSensorSteps(yesterDay);// 将今天的步数存入steps偏移量中,传入correctSensorSteps后会加上steps自身,详见Database代码db.updateSteps(today, correctSensorSteps);} else if (off == 1) {// 说明昨天关机,偏移量就是计步器的实际值correctSensorSteps = SensorListener.steps;db.updateSteps(today, correctSensorSteps);} else {// 计步器异常}// 将今天的sensor偏移量置为0,下面这三行代码是为了解决在关机时更新整个数据库不能完成的情况,// 这样在用户不随意修改系统时间时可以最优处理db.updateSensorSteps(today, 0);db.updateOffStatus(yesterDay, 1);db.updateOffStatus(today, 1);// 更新整个数据库将off置为1,sensor置为0, steps置为每天的步数db.updateAll();db.close();}
}
到这里大体思路都实现了,其他代码等我发布源码后查看。

Android计步器的实现(2)相关推荐

  1. Android计步器算法实现(2)

    Android计步器算法实现(2) 前言 算法实现的意义 现实原因 优缺点 算法原理 运动状态判断 计步原理 步长计算原理 Java实现 补充 观测点的作用 数据的存放方式 前言 在之前我也写过两篇关 ...

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

    本文只赘述Android计步器开发里计步的原理. 在Android4.4版本之后,新增了STEP_COUNTER和STEP_DECTECTOR STEP_COUNTER表示自从开机以来,你走的步数累计 ...

  3. Android计步器算法实现

    最近在研究惯性导航和其他导航算法的融合,顺手把计步.步长等一堆算法写成类了,舒服~ 这篇文章我不会具体的讲解实现原理,有兴趣研究的朋友直接看我写的计步算法实现和步长计算. Android系统有自带的计 ...

  4. Android计步器的实现(1)

    最近项目中要加一个计步器的功能,Github上搜索一堆,都是bug漫天飞(微信也有bug^_^,关于bug的原因有:异常开关机.调整手机时间. 正常开关机.跨天问题,这几种原因复合在一起更容易造成计步 ...

  5. Android计步器小Demo

    描述 android计步器的实现,自定义的一个弧形进度条,记步通过手机的传感器来实现,也就是说不支持传感器的机子(应该很老的了吧)就没有效果.看看效果图: 自定义View public class S ...

  6. android 计步器

    我们经常会看到微信 QQ 以及其他一些运动app里面都有一个计步功能,那它是怎么实现的呢? 今天我们就来实现一下,以下代码都是从一个整体项目中抽离出来的,为了理解简单方便我把UI部分数据保存部分全部都 ...

  7. android计步器开源,开源Android项目pedometer计步器源码

    [实例简介] 开源Android项目计步器源码,打开软件后,手握手机,可根据你走路时胳膊摆的次数准确测试出你走了多少步,有意思吧,而且这个项目的源码是开源的,分iPhone版和Android版,此为a ...

  8. Android 计步器实现

    前段时间系统应用到计步器,在网上看了好多,借鉴大神的代码完成了效果,最后还是决定写下来吧,万一哪天在用到了 .... 1.需要在AndroidManifest.xml中添加权限 <uses-pe ...

  9. android 计步器保活,计步器(Android和iOS)

    更新记录 1.1(2021-04-30) 修复ios打包问题 1.0(2021-03-31) 首发版本 查看更多 平台兼容性 Android iOS 适用版本区间:4.4 - 11.0 适用版本区间: ...

最新文章

  1. 理解计算机视觉中的损失函数
  2. (转)一个古老的编程游戏:Python Challenge全通攻略
  3. 仿Word自动套用格式,用CSS设置表格样式
  4. 7.泡妞与设计模式(八)模板模式
  5. 2014 网选 广州赛区 hdu 5023 A Corrupt Mayor's Performance Art
  6. Debian11安装VLC Media Player视频播放器
  7. 并行程序设计模式--Master-Worker模式
  8. 【2020模拟考试T2】【PAT乙】1032 挖掘机技术哪家强 (20分) 模拟,STL
  9. Java进阶:SpringMVC中通过监听器将Spring上下文对象放置到servletContext中,方便其他地方使用
  10. java中如何访问类中的字段_java – 在子类中使用super关键字访问超类私有字段
  11. 使用idea工具进行反编译
  12. 软件测试面试题【2021模拟面试整理版(含答案)】
  13. php 程序设计代码教程
  14. 纯净PE推荐——优启通 v3.3.2019.0605
  15. 用计算机做动画,如何制作动画
  16. 计算机组装的硬件配置及报价,2021组装电脑配置清单及价格表说明
  17. 视频教程-用Java从零开始开发一个物联网项目-物联网技术
  18. Java编程思想+Effective Java+Java核心技术+Java核心技术 卷II+Java语言程序设计(中文+英文+源码)
  19. Qt 使用阿里巴巴字体图标库 iconfont
  20. 现代密码学 | 02:流密码——1

热门文章

  1. mysql数据库导出表结构到excel表中
  2. ofo抵押单车获17.7亿元融资;董明珠回应与雷军赌局;亚马逊Alexa全球性“罢工”丨价值早报
  3. FFMPEG中av_log()函数
  4. [绍棠] PhotoKit介绍
  5. 从逻辑功能上计算机网络可以分为两部分,从逻辑功能上看计算机网络分为( )几部分...
  6. 高通Camera 驱动调试要点(一)
  7. 基于hive的《反贪风暴4》的影评
  8. 服务器显示隐藏任务,在Windows 10中隐藏任务栏的简单方法
  9. Eunomia: 让 ebpf 程序的分发和使用像网页和 web 服务一样自然
  10. winds主机部署zabbix_agent