文档章节

基于Android的计步器(Pedometer)的讲解(四)——后台记步

andyhe91
 andyhe91
发布于 2015/06/27 14:49
字数 1497
阅读 1382
收藏 21
  • 基于Android的计步器(Pedometer)的讲解(四)——后台记步

  • 2015-01-07      58 个评论    来源:a296777513的专栏   

  • 收藏    我要投稿

  • 今天先不说Pedometer(计步器)项目UI方面的了,今天讲一个基于重力加速度的记步功能传感器(Sensor),然后

    在后台开启记步。

     

    计步器(Pedometer)整个项目的源代码,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~)

     

    先上几张效果图:(效果和上一篇讲到的CircleBar非常的相似,因为记步功能在后台)

    \\

    如图所示,能根据你的一些基本参数,来记步。有一个缺点,因为这个是根据感应加速度来计算是否走一步,所以你在原地晃手机,也会记步,不过正常的走路还是挺准确的。

    首先给出StepDetector类的代码:

     

    ?

    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
    package com.example.histogram.widet;
     
    import android.content.Context;
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    import android.hardware.SensorManager;
     
    /**
      * 这是一个实现了信号监听的记步的类
      * 这是从谷歌找来的一个记步的算法,看不太懂
      * @author Liyachao Date:2015-1-6
      *
      */
    public class StepDetector implements SensorEventListener {
     
         public static int CURRENT_SETP = 0 ;
         public static float SENSITIVITY = 10 ; // SENSITIVITY灵敏度
         private float mLastValues[] = new float [ 3 * 2 ];
         private float mScale[] = new float [ 2 ];
         private float mYOffset;
         private static long end = 0 ;
         private static long start = 0 ;
         /**
          * 最后加速度方向
          */
         private float mLastDirections[] = new float [ 3 * 2 ];
         private float mLastExtremes[][] = { new float [ 3 * 2 ], new float [ 3 * 2 ] };
         private float mLastDiff[] = new float [ 3 * 2 ];
         private int mLastMatch = - 1 ;
     
         /**
          * 传入上下文的构造函数
          *
          * @param context
          */
         public StepDetector(Context context) {
             super ();
             int h = 480 ;
             mYOffset = h * 0 .5f;
             mScale[ 0 ] = -(h * 0 .5f * ( 1 .0f / (SensorManager.STANDARD_GRAVITY * 2 )));
             mScale[ 1 ] = -(h * 0 .5f * ( 1 .0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
         }
     
         //当传感器检测到的数值发生变化时就会调用这个方法
         public void onSensorChanged(SensorEvent event) {
             Sensor sensor = event.sensor;
             synchronized ( this ) {
                 if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
     
                     float vSum = 0 ;
                     for ( int i = 0 ; i < 3 ; i++) {
                         final float v = mYOffset + event.values[i] * mScale[ 1 ];
                         vSum += v;
                     }
                     int k = 0 ;
                     float v = vSum / 3 ;
     
                     float direction = (v > mLastValues[k] ? 1
                             : (v < mLastValues[k] ? - 1 : 0 ));
                     if (direction == -mLastDirections[k]) {
                         // Direction changed
                         int extType = (direction > 0 ? 0 : 1 ); // minumum or
                                                                 // maximum?
                         mLastExtremes[extType][k] = mLastValues[k];
                         float diff = Math.abs(mLastExtremes[extType][k]
                                 - mLastExtremes[ 1 - extType][k]);
     
                         if (diff > SENSITIVITY) {
                             boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k] * 2 / 3 );
                             boolean isPreviousLargeEnough = mLastDiff[k] > (diff / 3 );
                             boolean isNotContra = (mLastMatch != 1 - extType);
     
                             if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough
                                     && isNotContra) {
                                 end = System.currentTimeMillis();
                                 if (end - start > 500 ) { // 此时判断为走了一步
     
                                     CURRENT_SETP++;
                                     mLastMatch = extType;
                                     start = end;
                                 }
                             } else {
                                 mLastMatch = - 1 ;
                             }
                         }
                         mLastDiff[k] = diff;
                     }
                     mLastDirections[k] = direction;
                     mLastValues[k] = v;
                 }
     
             }
         }
         //当传感器的经度发生变化时就会调用这个方法,在这里没有用
         public void onAccuracyChanged(Sensor arg0, int arg1) {
     
         }
     
    }


    下来是后台服务StepService的代码:

     

     

    ?

    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
    package com.example.histogram.widet;
     
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.hardware.Sensor;
    import android.hardware.SensorManager;
    import android.os.IBinder;
     
    public class StepService extends Service {
         public static Boolean flag = false ;
         private SensorManager sensorManager;
         private StepDetector stepDetector;
     
         @Override
         public IBinder onBind(Intent arg0) {
             // TODO Auto-generated method stub
             return null ;
         }
     
         @Override
         public void onCreate() {
             super .onCreate();
             //这里开启了一个线程,因为后台服务也是在主线程中进行,这样可以安全点,防止主线程阻塞
             new Thread( new Runnable() {
                 public void run() {
                     startStepDetector();
                 }
             }).start();
     
         }
     
         private void startStepDetector() {
             flag = true ;
             stepDetector = new StepDetector( this );
             sensorManager = (SensorManager) this .getSystemService(SENSOR_SERVICE); //获取传感器管理器的实例
             Sensor sensor = sensorManager
                     .getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //获得传感器的类型,这里获得的类型是加速度传感器
             //此方法用来注册,只有注册过才会生效,参数:SensorEventListener的实例,Sensor的实例,更新速率
             sensorManager.registerListener(stepDetector, sensor,
                     SensorManager.SENSOR_DELAY_FASTEST);
         }
     
         @Override
         public int onStartCommand(Intent intent, int flags, int startId) {
             return super .onStartCommand(intent, flags, startId);
         }
     
         @Override
         public void onDestroy() {
             super .onDestroy();
             flag = false ;
             if (stepDetector != null ) {
                 sensorManager.unregisterListener(stepDetector);
             }
     
         }
    }


    最后把FragmentPedometer测试页面的代码也给大家,如果大家看过之前的博客,应该知道这是一个碎片。如果没看过,看兴趣的朋友可以看看之前的博文:

     

     

    ?

    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
    package com.example.histogram;
     
    import java.text.SimpleDateFormat;
    import java.util.Date;
     
     
     
     
     
     
    import com.example.changepage1.R;
    import com.example.histogram.widet.CircleBar;
    import com.example.histogram.widet.StepDetector;
    import com.example.histogram.widet.StepService;
    import com.example.histogram.widet.Weather;
     
     
     
    import android.annotation.SuppressLint;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.View.OnClickListener;
     
    /**
      * 这是记步的碎片
      * Author: 李垭超   email:296777513@qq.com
      * Date: 2015-1-6
      * Time: 下午8:39
      */
    public class FragmentPedometer extends Fragment implements OnClickListener{
         private View view;
         private CircleBar circleBar;
         private int total_step = 0 ;
         private Thread thread;
         private int Type = 1 ;
         private int calories = 0 ;
         private int step_length = 50 ;
         private int weight = 70 ;
         private Weather weather;
         private String test;
         private boolean flag = true ; // 来判断第三个页面是否开启动画
     
         @SuppressLint (HandlerLeak)
         Handler handler = new Handler() {
             public void handleMessage(Message msg) {
                 super .handleMessage(msg);
                 total_step = StepDetector.CURRENT_SETP;
                 if (Type == 1 ) {
                     circleBar.setProgress(total_step, Type);
                 } else if (Type == 2 ) {
                     calories = ( int ) (weight * total_step * step_length * 0.01 * 0.01 );
                     circleBar.setProgress(calories, Type);
                 } else if (Type == 3 ) {
                     if (flag) {
                         circleBar.startCustomAnimation();
                         flag = false ;
                     }
                     if (test != null || weather.getWeather() == null ) {
                         weather.setWeather(正在更新中...);
                         weather.setPtime();
                         weather.setTemp1();
                         weather.setTemp2();
                         circleBar.startCustomAnimation();
                         circleBar.setWeather(weather);
                     } else {
                         circleBar.setWeather(weather);
                     }
     
                 }
     
             }
     
         };
     
     
         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
                 Bundle savedInstanceState) {
             view = inflater.inflate(R.layout.pedometer, container, false );
             init();
             mThread();
             return view;
         }
         private void init() {      
             Intent intent = new Intent(getActivity(), StepService. class );
             getActivity().startService(intent);
             weather = new Weather();
             circleBar = (CircleBar) view.findViewById(R.id.progress_pedometer);
             circleBar.setMax( 10000 );
             circleBar.setProgress(StepDetector.CURRENT_SETP, 1 );
             circleBar.startCustomAnimation();
             circleBar.setOnClickListener( this );
     
         }
         
         private void mThread() {
             if (thread == null ) {
     
                 thread = new Thread( new Runnable() {
                     public void run() {
                         while ( true ) {
                             try {
                                 Thread.sleep( 500 );
                             } catch (InterruptedException e) {
                                 e.printStackTrace();
                             }
                             if (StepService.flag) {
                                 Message msg = new Message();
                                 handler.sendMessage(msg);
                             }
                         }
                     }
                 });
                 thread.start();
             }
         }
         @Override
         public void onClick(View v) {
             switch (v.getId()) {
             case R.id.progress_pedometer:
                 if (Type == 1 ) {
                     Type = 2 ;
                 } else if (Type == 2 ) {
                     flag = true ;
                     Type = 3 ;
                 } else if (Type == 3 ) {
                     Type = 1 ;
                 }
                 Message msg = new Message();
                 handler.sendMessage(msg);
                 break ;
             default :
                 break ;
             }
             
         }
     
    }


    © 著作权归作者所有

    共有 人打赏支持
    andyhe91
    粉丝 58
    博文 129
    码字总数 209109
    作品 0
    长沙
    加载中

    评论(1)

    orangebook
    orangebook
    嗯!不错,就是计步关键代码能,算法分析出来就好了
    Android 计步器应用 - healthgo

    healthgo a android pedometer app (安卓计步器) Support Android 4.1- 7.0 Thanks Project/People desc other Realm a mobile database 使用了这个数据库 EventBus a publish/subscribe eve......

    五十风
    04/13
    0
    0
    Android开发者必须深入学习的10个应用开源项目

    Android开发又将带来新一轮热潮,很多开发者都投入到这个浪潮中去了,创造了许许多 多相当优秀的应用。其中也有许许多多的开发者提供了应用开源项 目,贡献出他们的智 慧和创造力。 Android开...

    破晓之星
    2012/04/29
    0
    40
    Android计步模块优化(今日步数)

    最近在项目中研究计步模块,主要功能记录当天步数,类似微信运动,支付宝计步,咕咚今日步数。 开发之前的调研工作,搜遍baidu,google,github都没有找到我想要的demo和文章,大多数都是需要...

    jiahongfei
    2017/10/20
    0
    5
    Android 中文 API (101) —— AsyncTask

    Android 中文 API (101) —— AsyncTask 前言 本章内容是android.os.AsyncTask,版本为Android 2.3 r1,翻译来自"01",欢迎访问它的博客:"http://dev.10086.cn/blog/?32546",再次感谢"01" ...

    晨曦之光
    2012/03/15
    0
    0
    Android 第六课——Activity生命周期

    声明:本文转载自 http://blog.csdn.net/liuhe688/article/details/6733407 , 感觉读了这篇文章之后,对Activity又是一个更深层次的理解,所以果断手贱转载了!希望自己以后能多看看这篇文章...

    learn_more
    2015/01/02
    0
    0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    day63-20180821-流利阅读笔记-待学习

    性别歧视在日本:“我是女生,所以社会不让我学医” 毛西 2018-08-21 1.今日导读 大家在看病的时候,有留意过女医生的比例吗?在性别歧视现象十分严重的日本,男医生和女医生的比例达到了惊人...

    aibinxiao
    54分钟前
    2
    0
    Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

    解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

    AI_SKI
    今天
    4
    0
    深夜胡思乱想

    魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

    Firxiao
    今天
    1
    0
    MySQL 8 在 Windows 下安装及使用

    MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

    waylau
    今天
    2
    0
    微信第三方平台 access_token is invalid or not latest

    微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

    自由的开源
    今天
    3
    0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    返回顶部
    顶部