Android计步器,步数准确,可以切换日期
概述
详细
一、概述
Android计步器,步数准确,可以切换日期, UI美观
二、效果图
三、项目结构图截图
四、技术实现
1.计步器原理
(1) 在服务中开启计步检测会对API进行一个判断如果API>19则调用CountSensor,因为android4.4以后可以使用Google内置计步器。对于API<=19的手机可以使用加速度传感器
(a)对于安卓内置计步器来说,我们的做法是启动一个独立的进程PedometerStepService在后台跑,然后在service中注册这个计步器,安卓内置传感器会在步数变化的时候返回给我们步数,因为计步器有个普通的原则,一般都是以天作为单位,所以有些情况必须对返回的值对调整
(aa) 跨天我们必须对昨天的步数清零,并把昨天的步数存入数据库。(如果service在后台休眠或是被kill,那么这段时间的步数将丢失)
(bb)如果手机重启,那么这种情况下返回的步数有可能比重启之前的步数少,那么这个时候我们必须用重启之前的步数作为统计的起点, 如果判断手机重启呢,条件有两个,第一个条件是每次步数变化的时候我们保存SystemClock.elapsedRealtime(),如果发现注册service的时候发现SystemClock.elapsedRealtime()小于我们保存的时间,那么肯定是重启了,第二个如果传感器返回的数据比我们保存在shareprefrence中少的话那么也应该是重启了
(2) 步数换算成距离
float distance = steps * 0.7f / 1000 单位是公里
(3) 卡路里的计算:
getCalorieByStepRealValue(Context context, steps) { bodyWeight = SharePreferenceUtil.getInt(context, PemometerConstant.,PemometerConstant.); ()(steps * * bodyWeight * ) / ; }
2.对于计步器的记录以星期为单位查看的实现
(1)计步器表结构:
String = + + + + + + + + + + ; 有一个自增长的_id,每次插入步数,我们会判断当天的步数记录有没有存在,存在我们就更新这条九路,不存在我们就插入这条记录
(2)刚进入计步器,取最初的数据的逻辑:
(a)首先取数据库中最初一天的数据,这个应该是用户最早的运动记录,我们把这个数据称为firstData
(b) 获取当天所在星期的星期一的记录,然后查看从这个日期开始7天的记录,获取的数据放到一个List<TodayStepData> stepDataList,这个list是即使用户没有步数数据,我们也放把这条0的记录放到stepDataList里
(c) 如果stepList包含第一天的firstData,那这种情况,就说明用户就只有这个星期的记录,我们要的list就是
int index = stepDatas.indexOf(firstData);
stepDatas = stepDatas.subList(index,stepDatas.size()); 这样做的目的是用户不可以滑到没有运动记录的日期上去
(d) 如果stepList不包含第一天的fistData数据,那么用户就可以滑动到上个星期去查看上个星期的数据,这种情况下分两种情况,如果stepList只有一条数据,那么我们将上周日的记录也放到stepList返回
(2)我们页面采用ViewPager来实现的,计步器主页PedometerSportsStepActivity中有一个topList是星期的控件,然后底下是一个ViewPager,viewPager里面的adapter放的是PedometerDaySportStepsFragment,滑动的时候用viewPager的OnPageChangeListener的onPageSelected(int position)来处理,数据源放在
//存储的是viewpager当中adapter的数据源,mPagerListData的size有多少,用户就可以滑动多少页
private ArrayList<TodayStepData> mPagerListData = new ArrayList<>(); //TodayStepData这个数据结构包含目标步数,当天步数和日期
(3)处理用户右滑:
(a)如果滑过来的这页在当前星期内,那么就只要更新PedometerDaySportStepsFragment的内容和顶上星期控件的数据就成
(b)如果滑过来的这页在下个星期,那么我们就要更新mCurrentWeekStepDataList(里面存储的是这个星期的list的数据)的数据,然后更新
PedometerDaySportStepsFragment和顶上星期控件
(4)处理用户左滑:
(a)如果滑过来的这页在当前星期内,那么就只要更新PedometerDaySportStepsFragment的内容和顶上星期控件的数据就成
(b)如果滑过来的这页在上个星期,那么我们就要更新mCurrentWeekStepDataList(里面存储的是这个星期的list的数据)的数据,然后更新
PedometerDaySportStepsFragment和顶上星期控件
(c) 如果position=0,表示滑到左尽头了,那么我们就要取position=0这个日期的前一天的日期,跟我们数据库的第一条firstData相比,如果这个日期比firstData靠后,那么我们就往前取7天的数据放到mPagerList中,并更新当前页的ViewPager的viewIndex,注意要用 mViewPager.setCurrentItem(xx), false)这样没有滑动动作,用户无感知,可是可以又可以左滑了。
(5)通知栏和主App数据交互:
(a)因为通知栏是独立进程service启动的,这里采用AIDL和contentProvider来实现,首先定义PedometerProvider extends ContentProvider ,然后在service中注册并监听这个uri,
Uri notificationEnabledUri = Uri.parse("content://" + PedometerProvider.authory + "/notification/");
mNotificationObserver = new NotificationObserver(new Handler());
getContentResolver().registerContentObserver(notificationEnabledUri, true, mNotificationObserver); 然后在主程序中就可以发一些数据到通知栏,注意要用后台进程来发
(5)通知栏的圆形进度的实现:
remoteView不支持自定义view,可是安卓默认实现的ProgressBar不支持圆形进度,那么我们采用自己画drawable,然后转成bitmap,放到imageView里面实现
mProgressCircleView = new ProgressCircleView(context,realPercent);
remoteViews.setImageViewBitmap(R.id.pedometer_progress,drawableToBitmap(mProgressCircleView));
五、其他补充
没有