github 地址:https://github.com/zhouguangfu09/StepCounter

1.    程序图标

2.    点击图标,进入如下界面:

这个界面会有缓冲效果,然后进入程序的主界面.

3.程序主界面:

点击开始按钮,并甩动胳膊,计步器开始计数,也可以暂停计数,如下图所示:

5.每走150步,系统奖励一个星星,最高10颗星星。同时软件会粗略的计算行程、热量、速度等参数。如上图所示。

6.点击手机菜单键,点击“设置”选项,进入如下界面:

软件记步数的精准度跟用户的补偿以及体重有关,也跟用户设置的传感器的灵敏度有关系,在设置页面可以对相应的参数进行调节。一旦调节结束,可以重新开始。

7.在手机的主界面按返回键,退出程序。

源码部分解析

源码主要包含UI控制逻辑代码以及胳膊甩动检测步数代码,下面重点说一下 步数检测代码,主要集中在StepDector.java文件中:

       public void onSensorChanged(SensorEventevent) {// Log.i(Constant.STEP_SERVER, "StepDetector");Sensor sensor = event.sensor;// Log.i(Constant.STEP_DETECTOR,"onSensorChanged");synchronized (this) {if (sensor.getType() ==Sensor.TYPE_ORIENTATION) {} else {int j =(sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;if (j == 1) {float vSum =0;for (int i =0; i < 3; i++) {finalfloat v = mYOffset + event.values[i] * mScale[j];vSum+= v;}int k = 0;float v =vSum / 3;floatdirection = (v > mLastValues[k] ? 1: (v < mLastValues[k] ? -1 : 0));if (direction== -mLastDirections[k]) {//Direction changedintextType = (direction > 0 ? 0 : 1); // minumum or//maximum?mLastExtremes[extType][k]= mLastValues[k];floatdiff = Math.abs(mLastExtremes[extType][k]- mLastExtremes[1 - extType][k]);if(diff > SENSITIVITY) {booleanisAlmostAsLargeAsPrevious = diff > (mLastDiff[k] * 2 / 3);booleanisPreviousLargeEnough = mLastDiff[k] > (diff / 3);booleanisNotContra = (mLastMatch != 1 - extType);if(isAlmostAsLargeAsPrevious && isPreviousLargeEnough &&isNotContra) {end= System.currentTimeMillis();if(end - start > 500) {// 此时判断为走了一步Log.i("StepDetector","CURRENT_SETP:"+CURRENT_SETP);CURRENT_SETP++;mLastMatch= extType;start= end;}}else {mLastMatch= -1;}}mLastDiff[k]= diff;}mLastDirections[k]= direction;mLastValues[k]= v;}}}
}

这个函数是一个传感器的回调函数,在其中可以根据从系统地加速度传感器获取的数值进行胳膊甩动动作的判断。主要从以下几个方面判断:

(1)人如果走起来了,一般会连续多走几步。因此,如果没有连续4-5个波动,那么就极大可能是干扰。

(2)人走动的波动,比坐车产生的波动要大,因此可以看波峰波谷的高度,只检测高于某个高度的波峰波谷。

(3)人的反射神经决定了人快速动的极限,怎么都不可能两步之间小于0.2秒,因此间隔小于0.2秒的波峰波谷直接跳过

通过重力加速计感应,重力变化的方向,大小。与正常走路或跑步时的重力变化比对,达到一定相似度时认为是在走路或跑步。实现起来很简单,只要手机有重力感应器就能实现。

1.    启动界面

程序启动界面带有缓冲效果,其中界面缓冲效果的配置文件在res/anim/目录下。如果计步器已经开始工作,则跳过程序启动界面,直接进入主界面。

       if (StepCounterService.FLAG || StepDetector.CURRENT_SETP > 0) {// 程序已经启动,直接跳转到运行界面Intent intent = new Intent(SplashActivity.this,StepCounterActivity.class); //创建一个新的Intent,指定当前应用程序上下文
//和要启动的StepActivity类startActivity(intent);                                         //传递这个intent给startActivitythis.finish();} else {this.requestWindowFeature(Window.FEATURE_NO_TITLE);this.setContentView(R.layout.splash);animation = AnimationUtils.loadAnimation(SplashActivity.this,R.anim.animation_splash);this.findViewById(R.id.iv_index).setAnimation(animation);animation.setAnimationListener(new AnimationListener() {// 动画监听,通过AnimationListener可以监听Animation的运行过程@Overridepublic void onAnimationStart(Animation animation){// TODOAuto-generated method stub}@Overridepublic void onAnimationRepeat(Animationanimation) {// TODOAuto-generated method stub}@Overridepublic void onAnimationEnd(Animation animation) {// 动画结束时跳转至运行界面// TODOAuto-generated method stubIntent intent = new Intent(SplashActivity.this,StepCounterActivity.class);SplashActivity.this.startActivity(intent);SplashActivity.this.finish();}});}
}

2.  程序主界面

(1)界面元素的初始化(比如步数,星期,日期,运行时间,行程,卡路里,速度,开始按钮和停止按钮)。

 //定义文本框控件private TextView tv_show_step;// 步数private TextView tv_week_day;// 星期private TextView tv_date;// 日期private TextView tv_timer;// 运行时间private TextView tv_distance;// 行程private TextView tv_calories;// 卡路里private TextView tv_velocity;// 速度private Button btn_start;// 开始按钮private Button btn_stop;// 停止按钮// 十颗星标private ImageView iv_star_1;               private ImageView iv_star_2;private ImageView iv_star_3;private ImageView iv_star_4;private ImageView iv_star_5;private ImageView iv_star_6;private ImageView iv_star_7;private ImageView iv_star_8;private ImageView iv_star_9;private ImageView iv_star_10;private long timer = 0;// 运动时间private static long startTimer = 0;// 开始时间private static long tempTime = 0;private Double distance = 0.0;// 路程:米private Double calories = 0.0;// 热量:卡路里private Double velocity = 0.0;// 速度:米每秒private int step_length = 0;  //步长private int weight = 0;       //体重private int total_step = 0;   //走的总步数DatagramSocket socket;InetAddress serverAddress;DatagramPacket  send_package1;private Thread thread;  //定义线程对象

(2)利用消息机制对主界面的UI元素进行更新。定义了一个handler,当检测的步数变化时,更新主界面显示的信息。主要代码如下:

    Handler handler = new Handler() {// Handler对象用于更新当前步数,定时发送消息,调用方法查询数据用于显示??????????//主要接受子线程发送的数据, 并用此数据配合主线程更新UI//Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据,//Handler就承担着接受子线程传过来的(子线程用sendMessage()方法传递Message对象,(里面包含数据)//把这些消息放入主线程队列中,配合主线程进行更新UI。@Override                  //这个方法是从父类/接口继承过来的,需要重写一次public void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);        // 此处可以更新UIcountDistance();     //调用距离方法,看一下走了多远if (timer != 0 && distance != 0.0) {// 体重、距离// 跑步热量(kcal)=体重(kg)×距离(公里)×1.036calories = weight * distance * 0.001;//速度velocityvelocity = distance * 1000 / timer;} else {calories =0.0;velocity =0.0;}countStep();          //调用步数方法tv_show_step.setText(total_step + "");// 显示当前步数tv_distance.setText(formatDouble(distance));// 显示路程tv_calories.setText(formatDouble(calories));// 显示卡路里tv_velocity.setText(formatDouble(velocity));// 显示速度tv_timer.setText(getFormatTime(timer));// 显示当前运行时间changeStep();// 设置当前步数和星标}

(3)初始化主界面的信息。

    /*** 初始化界面*/private void init() {step_length =SettingsActivity.sharedPreferences.getInt(SettingsActivity.STEP_LENGTH_VALUE, 70);weight =SettingsActivity.sharedPreferences.getInt(SettingsActivity.WEIGHT_VALUE, 50);countDistance();countStep();if ((timer += tempTime) != 0 && distance != 0.0) {  //tempTime记录运动的总时间,timer记录每次运动时间// 体重、距离// 跑步热量(kcal)=体重(kg)×距离(公里)×1.036,换算一下calories = weight * distance * 0.001;velocity = distance * 1000 / timer;} else {calories = 0.0;velocity = 0.0;}tv_timer.setText(getFormatTime(timer + tempTime));tv_distance.setText(formatDouble(distance));tv_calories.setText(formatDouble(calories));tv_velocity.setText(formatDouble(velocity));tv_show_step.setText(total_step + "");btn_start.setEnabled(!StepCounterService.FLAG);btn_stop.setEnabled(StepCounterService.FLAG);if(StepCounterService.FLAG) {btn_stop.setText(getString(R.string.pause));} else if (StepDetector.CURRENT_SETP > 0) {btn_stop.setEnabled(true);btn_stop.setText(getString(R.string.cancel));}setDate();}

(4)计算距离和步长。

    /*** 计算行走的距离                                                                       */private void countDistance() {if (StepDetector.CURRENT_SETP % 2 == 0) {distance = (StepDetector.CURRENT_SETP / 2) * 3 * step_length * 0.01;} else {distance = ((StepDetector.CURRENT_SETP / 2) * 3 + 1) * step_length * 0.01;}}/*** 实际的步数*/private void countStep() {if (StepDetector.CURRENT_SETP % 2 == 0) {total_step = StepDetector.CURRENT_SETP;} else {total_step = StepDetector.CURRENT_SETP +1;}total_step = StepDetector.CURRENT_SETP;}

3.    后台检测传感器信息的服务(service).

//service负责后台的需要长期运行的任务// 计步器服务// 运行在后台的服务程序,完成了界面部分的开发后// 就可以开发后台的服务类StepService// 注册或注销传感器监听器,在手机屏幕状态栏显示通知,与StepActivity进行通信,走过的步数记到哪里了???
public class StepCounterService extends Service {public static Boolean FLAG = false;// 服务运行标志private SensorManagermSensorManager;// 传感器服务private StepDetector detector;// 传感器监听对象private PowerManager mPowerManager;// 电源管理服务private WakeLock mWakeLock;// 屏幕灯@Overridepublic IBinder onBind(Intent intent) {// TODOAuto-generated method stubreturn null;}@Overridepublic void onCreate() {// TODOAuto-generated method stubsuper.onCreate();FLAG = true;// 标记为服务正在运行// 创建监听器类,实例化监听对象detector = new StepDetector(this);// 获取传感器的服务,初始化传感器mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);// 注册传感器,注册监听器mSensorManager.registerListener(detector,mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_FASTEST);// 电源管理服务mPowerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP, "S");mWakeLock.acquire();}@Overridepublic void onDestroy() {// TODOAuto-generated method stubsuper.onDestroy();FLAG = false;// 服务停止if (detector != null) {mSensorManager.unregisterListener(detector);}if (mWakeLock != null) {mWakeLock.release();}}

Android 计步器开发相关推荐

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

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

  2. Android项目开发:简易计步器

    Android项目开发:简易计步器的实现 本文将介绍基于Android的加速度传感器和陀螺仪传感器开发一个简易的计步器,基本原理:当检测到加速度发生改变时,使步数加一. activity_main.x ...

  3. android精准计步器,Android 超精准计步器开发 - Dylan 计步

    Android超精准计步器开发 亲测在小米.魅族.华为上可用,该app采用后台service计歩服务,所以只要app不被手机杀死在后台也是可以正常计歩的.上图: 1.需要在AndroidManifes ...

  4. Android移动开发-调用步行检测和步行计数传感器开发简易计步器的实现

    Android计步器的原理其实是通过手机的前后摆动模拟步伐节奏的监测.Android中与计步器有关的传感器有两个,一个是步行检测(TYPE_STEP_DETECTOR),另一个是步行计数(TYPE_S ...

  5. 《Android/OPhone 开发完全讲义》样章和目录下载

    <Android/OPhone 开发完全讲义>一书已经出版,现提供3个样章(第1.8和14章)试读,欢迎提出宝贵意见. 购买:互动网(china-pub) 内容简介 本书近500页,共25 ...

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

    在上一节<Android硬件开发------传感器介绍>中,简单介绍了Android手机的传感器类型,通过SensorManager引出传感器的使用方法,通过注册监听器,监听传感器返回的参 ...

  7. Android Wear开发浅析(一)

    Android Wear究竟是什么? Android Wear和手机是完全不同的设计理念:手机大多数情况下,都是用户去操作,去触发里面的应用:而手表则是"用户被动"的,用户越少感觉 ...

  8. Android Wear 开发 (一)

    [转载博客](http://blog.csdn.net/hehaitao074/article/details/50675618) Android Wear究竟是什么? Android Wear和手机 ...

  9. 《Android/OPhone 开发完全讲义》目录

    目录 前言 第1章 Android入门 1 1.1 Android的基本概念 1 1.1.1 Android简介 1 1.1.2 Android的系统构架 3 1.2 Android开发环境的搭建 4 ...

最新文章

  1. Objective-C中的一些特殊的数据类型
  2. LeetCode Increasing Triplet Subsequence(动态规划)
  3. java new 删除吗,java泛型对象初始化-java泛型对象会实例化吗T t=new T()
  4. php网站灰颜色代码,css取消Safari浏览器链接点击颜色变灰-webkit-tap-highlight-color_html/css_WEB-ITnose...
  5. VSCode配置Python开发环境
  6. 在ubuntu中搭建guacamole
  7. 单元测试之误解与困境
  8. 地表净辐射通量数据、太阳辐射量数据、降雨量数据、气温数据、日照时长、水汽压分布、风速风向数据、地表温度
  9. c语言局域网聊天项目,局域网聊天的程序(C++版)
  10. 电子海图系统线状符号表达及绘制方法
  11. vs使用安装devexpress教程
  12. Redis跳跃表源码解析
  13. 基础 | 并发编程 - [LongAdder Striped64]
  14. arm linux建站,arm服务器做虚拟机(arm平台虚拟机)
  15. python -- 最长公共子串
  16. 【微信小程序】云开发基础设置
  17. 为什么索引不支持模糊查询_美团王兴:淘宝为什么不支持微信支付?
  18. 《各领域机器学习数据集汇总(附下载地址)》
  19. 存储在icloud云盘文件夹顶层_iCloud云盘文件夹共享功能使用方法
  20. 文件上传与下载的场景梳理

热门文章

  1. Flutter基础之水平方向列表布局
  2. 如何与强势的人相处zz
  3. Python——蓝桥杯
  4. 主分会场视频互动连线,如何使用SRT传输技术?
  5. 数据竞赛技巧|数据挖掘(四):常用trick介绍
  6. 【设计鉴赏】毛笔书法作品欣赏
  7. 前端制作水果忍者小游戏
  8. flutter中dynamic、var和Object的区别
  9. 图书管理分类统计c语言,图书管理完整系统(c语言).doc
  10. 电子信息、电气、计算机类专业中外合作硕士项目一览