步数传感器:Android计步模块优化(今日步数)
原标题:Android计步模块优化(今日步数)
最近在项目中研究计步模块,主要功能记录当天步数,类似微信运动,支付宝计步,咕咚今日步数。
开发之前的调研工作,搜遍baidu,google,github都没有找到我想要的demo和文章,大多数都是需要Service保活。
对于各大手机厂商为了提高电池的续航里程AlertManager、BOOT_COMPLETED、Service的START_STICKY基本上都是不起作用的,Service后台保活更是不可能。
下面是我实现的计步模块和大家一起学习
Github地址:
App计步模块优化的三个过程
第一个过程上线:
由于功能着急上线,项目最开始计步模块单独使用加速度传感器Sensor.TYPE_ACCELEROMETER进行计算步数,同时Service需要在后台存活才能计步,否则不能计步。
第二个过程计步器:
项目运行一段时间公司开始推广走路计步这个模块,所以开始重新开发计步模块,这次使用了Android4.4以上提供的计步传感器Sensor.TYPE_STEP_COUNTER来完成,这次重新开发整个计步模块有了质的飞跃,由于采用了计步传感器不在需要后台保活Service,同时计步传感器的功耗特别低,整个模块也更省电了。
第三个过程优化计步:
用户量变大了投诉也变多了,android各种各样的机型真是让人蛋疼,终于到了第三个阶段优化阶段。
目前最多的问题:
1.Android4.4以上的系统但是手机没有计步协处理器
2.部分手机步数出现暴增现象,有可能一天几十万步
3.部分手机出现一天清零好多次。
4.开机计步不能自启动,需要打开app(我已经监听BOOT_COMPLETED广播)
5.隔天分隔(0点分隔)不好用每天早上需要打开app(我已经设置AlertManager)
这篇文章就来介绍现在app的计步模块,已经解决上述问题1、2、3,至于4、5问题是系统问题正在寻找解决方案,大家也可以帮帮忙在评论中给我提示。
已经将计步模块单独封装成libModule上传github如果有开发者需要的或者想交流的可以很方便的使用下载,点击这里下载。
计步方式背景知识
1.加速度传感器Sensor.TYPE_ACCELEROMETER计步方式:
这种方式是有开源的算法根据加速度传感器进行计算步数,点击这里查看原作者源码;优点:只要有加速度传感器的设备都可以使用,相对来说可以使用的设备较多。
缺点:步数的准确性取决于算法且算法比较难优化;需要后台保活Service否则不能计步;计步算法比较费电;部分手机锁屏不能计步;
2.计步传感器Sensor.TYPE_STEP_COUNTER计步方式:
官方解释翻译(本人英文不是很好根据理解翻译,如有错误请指出):
这个传感器是返回手机系统启动到当前时间的所有步数。手机系统重启传感器返回步数为0。还返回一个时间戳,表示最后一次步数的时间。这个计步传感器是个硬件,功耗非常低。如果你想记录步数,注册该传感器不要注销,他能自动在后台计步,在app唤醒的时候会返回计步总数。应用程序需要注册该传感器,否则不能返回步数。
优点:硬件计步准确性高;功耗小;只要注册不用后台Service自动计步;
缺点:Android4.4系统以上的部分手机;手机系统重启计步器清零;不能返回步数明细(步数对应时间),只是返回当前时间的总步数。
计步模块两种计步方式都采用:
判断是否支持Sensor.TYPE_STEP_COUNTER如果支持采用计步传感器,如果不支持用加速度传感器计步。
使用加速度传感器计步需要用户自己手动设置后台自启动,否则不能计步。
使用计步传感器需要在程序中克服他的缺点:手机系统重启计步器清零;不能返回步数明细(步数对应时间),只是返回当前时间的总步数。
先介绍接入方法,在介绍计步模块原理
接入方法
1.先下载计步demo TodayStepCounter
2.demo项目结构如下图:
由图可见todaystepcounterlib是计步模块封装好的Module,它对外提供的接口就是ISportStepInterface.aidl
3.如何接入:
查看对外接口ISportStepInterface.aidl如下代码:
// ISportStepInterface.aidl
package com.today.step.lib;
interfaceISportStepInterface{
intgetCurrentTimeSportStep();
String getTodaySportStepArray();
}
查看使用代码MainActivity.java,里面关键代码有注释非常简单
publicclassMainActivityextendsAppCompatActivity{
privatestaticString TAG="MainActivity";
privatestaticfinalintREFRESH_STEP_WHAT=0;
//循环取当前时刻的步数中间的间隔时间
privatelongTIME_INTERVAL_REFRESH=500;
privateHandler mDelayHandler=newHandler( newTodayStepCounterCall);
privateintmStepSum;
privateISportStepInterface iSportStepInterface;
privateTextView mStepArrayTextView;
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化计步模块
TodayStepManager.init(getApplication);
mStepArrayTextView=(TextView)findViewById(R.id.stepArrayTextView);
//开启计步Service,同时绑定Activity进行aidl通信
Intent intent=newIntent( this, TodayStepService.class);
startService(intent);
bindService(intent, newServiceConnection {
@Override
publicvoidonServiceConnected(ComponentName name, IBinder service){
//Activity和Service通过aidl进行通信
iSportStepInterface=ISportStepInterface.Stub.asInterface(service);
try{
mStepSum=iSportStepInterface.getCurrentTimeSportStep;
updateStepCount;
} catch(RemoteException e) {
e.printStackTrace;
}
mDelayHandler.sendEmptyMessageDelayed(REFRESH_STEP_WHAT, TIME_INTERVAL_REFRESH);
}
@Override
publicvoidonServiceDisconnected(ComponentName name){
}
}, Context.BIND_AUTO_CREATE);
}
classTodayStepCounterCallimplementsHandler.Callback{
@Override
publicbooleanhandleMessage(Message msg){
switch(msg.what) {
caseREFRESH_STEP_WHAT: {
//每隔500毫秒获取一次计步数据刷新UI
if( null!=iSportStepInterface) {
intstep=0;
try{
step=iSportStepInterface.getCurrentTimeSportStep;
} catch(RemoteException e) {
e.printStackTrace;
}
if(mStepSum !=step) {
mStepSum=step;
updateStepCount;
}
}
mDelayHandler.sendEmptyMessageDelayed(REFRESH_STEP_WHAT, TIME_INTERVAL_REFRESH);
break;
}
}
returnfalse;
}
}
privatevoidupdateStepCount{
Log.e(TAG, "updateStepCount : "+ mStepSum);
TextView stepTextView=(TextView)findViewById(R.id.stepTextView);
stepTextView.setText(mStepSum + "步");
}
publicvoidonClick(View view){
switch(view.getId){
caseR.id.stepArrayButton:{
//显示当天计步数据详细,步数对应当前时间
if( null!=iSportStepInterface){
try{
String stepArray=iSportStepInterface.getTodaySportStepArray;
mStepArrayTextView.setText(stepArray);
} catch(RemoteException e) {
e.printStackTrace;
}
}
break;
}
default: break;
}
}
}
计步模块原理计步模块流程图
讲解流程图:
1.整个计步模块是由一个运行在单独进程的Service(TodayStepService)来提供,由于运行在单独的进程所以对外提供的接口采用aidl形式(ISportStepInterface)。
2.零点分隔广播(TodayStepAlertReceive):用来解决跨天计步模块归零问题,由于计步传感器不会根据天来分割只是返回当前步数的总和,所以需要这个广播来对计步模块进行分割,只要跨天了计步模块就归零从0开始计步。
3.开机广播(TodayStepBootCompleteReceiver):开机广播用来解决手机重启计步传感器归零问题,由于计步传感器手机重启会归零,所以收到开机广播会做步数合并,启动Service从上次关机的步数开始累加。
4.数据库(TodayStepDBHelper):用来记录当天步数明细,一个时间对应一个步数
5.加速度传感器计步(TodayStepDcretor):由于android4.4以下或者一些特殊的手机不提供计步传感器所以这些机型采用加速度传感器进行计步,通过OnStepCounterListener监听返回给TodayStepService .
6.计步传感器计步(TodayStepCounter):android4.4以上提供了计步协处理器,可以通过计步传感器计步功耗小,计步准,通过OnStepCounterListener监听返回给TodayStepService .
7.关机监听(TodayStepShutdownReceiver):用来判断手机是否关机,当重启手机打开计步Service根据这个标志来判断是否重启进行步数合并,主要是增加精度有时开机广播不能收到。
加速度传感器计步流程图
讲解流程图:
Android4.4以下或者一些特殊的手机不提供计步传感器,我只能用加速度传感器计步,加速度传感器的原理就是利用一定的算法模拟出步数(加速度传感器计步算法不在本篇文章讨论的范围之内),用这种方式计步Service一定要在后台存活否则不能计步,这种方式跨天分隔步数利用Intent.ACTION_TIME_TICK广播回调来判断当前时间和上次PreferencesHelper记录的时间是否相同如果不同步数归零从0开始计步,步数的记录采用PreferencesHelper来保存,防止当天重启手机系统步数归零。
计步传感器计步流程图
讲解流程图:
Android4.4以上的可以使用计步传感器进行计步,至于计步传感器的有点上面已经介绍了。这种方式部分手机可以不需要程序自启动权限。
跨天分隔步数采用两种方式:
1.第一种方式和上面一样采用Intent.ACTION_TIME_TICK广播,这里不多说了。
2.第二种方式采用AlertManager方式也就是设置0点闹钟,在这个0点广播中对步数进行分隔,这个AlertManager不是每个手机都可以启动的。
手机系统重启判断采用四种方式:
1.开机广播监听BOOT_COMPLETED,这个监听不是每个手机都可以收到,如果收到可以启动Service,然后做步数合并使计步模块从上次关机时的步数开始累加,如果收不到只能用下面几种方式增加重启的判断了。
2.关机广播监听ACTION_SHUTDOWN,这个监听不是每个手机都可以收到,如果收到,在用户手动启动 Service中可以判断系统重启了。
3.记录运行时间判断手机重启,上次运行的时间大于当前运行时间判断为重启,只是增加精度,极端情况下连续重启,会判断不出来。
4.上次传感器步数总和,当前传感器步数小于上次传感器步数肯定是重新启动了,只是用来增加精度不是绝对的
计步传感器计步核心流程
这个流程图的讲解都在图片上。
提高计步精度:
1.设置app后台自启动
2.各种安全软件设置app为白名单,为了保证app不被任何安全软件在后台杀死。
以上两种方式保证通知栏中一直显示app的步数。
3.手机系统重启,如果通知栏中没有显示步数,表示app没有收到开机监听,需要手动启动app,否则步数会丢失 。
app一直在后台存活肯定会耗电,部分手机可以在后台关闭的情况下计步,但是这种方式需要每天早上打开一次app让计步模块对步数进行清零否则步数会丢失。
需要优化:
1.每次传感器回调都会写三次SharedPreferences。
2.计步模块在后台存活,每天过0点开始计步都会丢失一些步数,丢失的步数跟启动计步传感器需要的步数有关,例如:我的测试机连续走10步才可以启动计步传感器回调,所以就丢失10步。
总结:
Android计步就是在和android系统作斗争,各种系统监听回调都不好用(AlertManager、BOOT_COMPLETED、JobScheduler),还要解决计步传感器的一些限制(系统重启清零,不能自动分天,部分手机进程杀死不能计步),还要规避不同手机的问题,我们只能尽量做到不丢失步数,提高计步精度,目前我在测试计步发现支付宝计步非常准,我猜测系统为支付宝做了系统进程。
只有不断天坑,优化,增加计步准确性,也请个位大神下载代码一起交流。
特此感谢 作者返回搜狐,查看更多
责任编辑:
步数传感器:为什么手机能计算出我们行走的步数加速度传感器起到了什么样的作用
描述
随着科技的高速发展,智能手机的功能也越来越强大,很多手机中都有计算步数的功能,为什么手机能计算出我们行走的步数呢?
▲手机计算行走步数
计步器最早是由意大利的伦纳德·达芬奇想出来的,由于当时技术水平有限,直到150年后的1667年,计步器才真正的做出来,早期计步机比较简陋,还是机械式的。
▲早期机械式计步器
机械式计步器的原理很简单,就跟摆锤一样。人在走路的时候,计步器里的摆锤会随着摆动,人走一步摆锤就动一下,金属摆锤摆动一下会和金属电极接触通电,这样就记录了一个步数。
现在主流的计步软件(以微信运动为例),是通过手机内置的陀螺仪、重力感应器和加速器度传感器等组合完成的,根据这些设备的震动频率来储存数据,从而计算出每天走路的步数。
其中陀螺仪可以测量出手机的角度,从而检测到人体的重心偏移。当人在行走时,手机会随着运动出现角度偏移。陀螺仪检测到持续且有规律的角度偏移时,手机就会开始判断用户正在走路。
▲手机内置的陀螺仪
陀螺仪还可以判断用户是在走路还是在骑自行车。由于骑车过程相对走路时,人体姿态更加平稳,重心偏移量很小,陀螺仪收集到的角度变化也很小。
▲手机内置的陀螺仪结构
当我们携带手机走路时,每一步都经历了过山车般的加速度变化。抬腿迈出第一步的时候,加速度是最大的。我们把它放到一个坐标轴上,加速度的变化看起来就像一个cos波形。两个波峰之间,可以被认为是走了一步。
如果连续出现几个波峰,就可以基本确定用户是在走路的状态。传感器设备就把这些前面的波动以及后面的波动算成步数,记录到手机里。
在实际场景中,算法还要去掉一些“干扰项”。比如我们走路时,手机放兜里会上下抖动,产生不同方向的加速度。这时算法就要判断并过滤掉无用的干扰项,只留下最主要的运动特征。
手机里的压电陶瓷也会根据力的大小产生不同的形变,从而产生不同的电压变化,通过作用在上面的力测量出加速度,计算用户在走路时的频率大小。
其实就是手机硬件的重力感应,比如我们看电影转动手机时,屏幕会自动跟着转,就是它感应到向下重力作出的反应。
更加精确的计步软件还会辅助利用GPS来定位用户的运动路线,然后计算出平均时速。
上述的这些工作是由采集器(加速度传感器等)和处理器(Sensor Hub,协处理器)共同完成的。
其实计步功能只是加速度传感器的一部分应用。在车辆安全、桥梁健康等方面,加速度传感器也有着非常重要的作用。
当汽车在高速行驶时速度突然降下来,安全气囊就会弹出来。这里有一个加速度传感器测量车辆在前进方向的负加速度,从而判断是否应该将安全气囊弹出。
打开APP阅读更多精彩内容
步数传感器:计步传感器TYPE_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="今日步数";
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);
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);
}
步数传感器:谜底揭晓——计步器如何知道我们每天走的步数?
原标题:谜底揭晓——计步器如何知道我们每天走的步数?
随着生活质量的提高,越来越多的人会注重自己的身体健康,所以很多人对自己每天的运动量也越来越关注,不管是佩戴手环、携带计时器还是拿手机,每天记录自己行走的步数,这已经成为了很多人的日常习惯。那计步器到底是如何知道我们每天走了多少步的呢,必优传感小编带你了解一下。
据了解,最开始的计步器是机械式的,原理跟摆锤一样。摆锤会随着人的走动而摆动,它动一下,基本上就是人在走一步。然后摆锤动一下,和金属接触通电,就记了一步。
那如今流行的智能手环和手机里的计步软件也是这个原理吗?其实我们现在用的手机手环里面,有一个非常小的芯片,叫三轴加速度传感器。通过这个加速度传感器,可以测量手机或者是手环在三个不同方向上的加速度。然后通过对这个加速度的值进行计算,就可以大概测出走路的步数。
而这种加速度传感器是怎么知道我们走路的步数呢?有一种特殊的材料,叫压电陶瓷材料,根据作用在上面力的大小产生不同的形变,就可以产生不同的电压变化,通过作用在上面的力来测量出加速度,然后通过加速度就能够判断出人在走路的时候,他是在哪个方向进行运动,或者说频率大概是多少。
加速度传感器的应用有很多,计步功能只是加速度传感器的一部分应用。在车辆安全、桥梁健康等方面,加速度传感器都有着非常重要的作用。
传感器技术与计算机技术,通信技术并称为现代信息技术的三大支柱。在航天运载火箭和高铁运行上上,采用的传感器就高达2000多个;一架民航客机所用的传感器也有上千个。可以说,任何自动控制装置和系统都离不开传感器技术。
全球领先传感器行业互联网+垂直平台。专业、高效、全面、经济!买传感器找必优、卖传感器找必优文章侵删!返回搜狐,查看更多
责任编辑:
您可能感兴趣的文章
- 传感器样本:E2B
- 光亮传感器:传感器和医疗器械有哪些联系?这篇图文分解为你展示应用案例
- 水位传感器坏了的表现:如何判断洗衣机水位传感器坏
- 索尼298传感器:索尼 IMX 传感器大起底,看完就再不用被手机拍照广告忽悠了!
- 传感器测控:传感器测控
- 西门子温度传感器:西门子传感器
- 轮速传感器多少钱:找论坛全部车系全部地区全部主题摩托车论坛
- cmp传感器:cmp传感器是什么
- 车的氧传感器:在国内,多少钱的车才可以被称作“豪车”?内行人:我说的很客观
- 压缩传感器:一种基于边缘压缩计算处理温度传感器数据的方法
- 指纹传感器发生错误:Thinkpad 录入指纹不成功的解决方法
- 精密位移传感器:拉绳位移传感器对于安装在设备上的直线运动物体的测量
- 谐振传感器:MEMS谐振式加速度传感器工作原理
文章标签:传感器 , 加速度传感器 , 速度传感器
版权声明:本文为原创文章,版权归 ceomba 所有,欢迎分享本文,转载请保留出处!
评论已关闭!