文档章节

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

andyhe91
 andyhe91
发布于 2015/06/27 14:49
字数 1497
阅读 1365
收藏 21
点赞 0
评论 1
  • 基于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
    博文 124
    码字总数 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

    Unity发布Android版本

    先大概说一下我自己的经历吧,总的大概用了10小时吧。刚开始装的是jre和Android stdio,然后发现要装的是JDK和SDK,然后去装JDK和SDK,装JDK很顺利,装SDK失败了,原因未知。后面是用 Androi...

    a_clear_chen ⋅ 05/08 ⋅ 0

    Android JNI(一)——NDK与JNI基础

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

    隔壁老李头 ⋅ 05/09 ⋅ 0

    Android JNI学习(二)——实战JNI之“hello world”

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

    隔壁老李头 ⋅ 05/09 ⋅ 0

    20个值得学习的优秀开源框架,应用开发者必备精选

    一、BeautifulRefreshLayout-漂亮的美食下拉刷新 项目地址 github.com/android-cjj… 二、基于zxing的二维码扫描,速度快,界面美观,可以自定义 项目地址 github.com/shuijilove/…) 三、模...

    codeGoogle ⋅ 2017/11/20 ⋅ 0

    【我的Android进阶之旅】Android自定义Lint实践

    一、Lint介绍 android lint是一个静态代码分析工具,通过lint工具,你可以不用边运行边调试,或者通过单元测试进行代码检查,可以检测代码中不规范、不和要求的问题,解决一些潜在的bug。lin...

    qq446282412 ⋅ 05/19 ⋅ 0

    2018 Google I/O放出6个大招,AI打电话能骗过人类

    Google I/O 谷歌开发者大会 为期三天的Google I/O开发者大会在美国开幕。在刚刚结束的主题演讲上,谷歌CEO桑达尔-皮查伊(Sundar Pichai)和各产品线负责人讲解了自家的AI、Android系统、谷歌...

    micf435p6d221ssdld2 ⋅ 05/10 ⋅ 0

    2018 Android 面试心得,已拿到 offer

    code小生,一个专注于 Android 领域的技术分享平台 作者:huisonma 链接:https://www.jianshu.com/p/855ff21e0a13 声明:本文是 huisonma 原创,转发等请联系原作者授权。 从 16 年毕业至今...

    h176nhx7 ⋅ 04/16 ⋅ 0

    Android 文件目录存储介绍 缓存目录 | 私有目录 | 系统根目录 | 用户可见目录

    先简要介绍一下Android系统的文件系统吧,本文基于原生Android M系统: 我们都知道Android系统内核就是个Linux、所以我们的文件系统与Linux也是基本一致的,最顶部的目录是 “/” 接下来就是...

    a_zhon ⋅ 04/25 ⋅ 0

    华为云测平台服务再升级!华为M5系列平板调测能力正式上线!

    6月1日,华为M5系列平板设备兼容性测试和远程真机调试功能在华为终端开放实验室正式上线!助力您的产品在大屏适配上快人一步! 华为终端开放实验室DevEco平台现已提供基于华为M5系列平板设备...

    华为终端开放实验室 ⋅ 06/08 ⋅ 0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    Gitee 生成并部署SSH key

    1.如何生成ssh公钥 你可以按如下命令来生成 sshkey: ssh-keygen -t rsa -C "xxxxx@xxxxx.com" # Generating public/private rsa key pair...# 三次回车即可生成 ssh key 查看你的 ...

    晨猫 ⋅ 34分钟前 ⋅ 0

    zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

    最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

    原创小博客 ⋅ 今天 ⋅ 0

    聊聊spring cloud的HystrixCircuitBreakerConfiguration

    序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

    go4it ⋅ 今天 ⋅ 0

    二分查找

    二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

    人觉非常君 ⋅ 今天 ⋅ 0

    VS中使用X64汇编

    需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

    simpower ⋅ 今天 ⋅ 0

    ThreadPoolExecutor

    ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

    4rnold ⋅ 昨天 ⋅ 0

    Java正无穷大、负无穷大以及NaN

    问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

    young_chen ⋅ 昨天 ⋅ 0

    前台对中文编码,后台解码

    前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

    west_coast ⋅ 昨天 ⋅ 0

    实验楼—MySQL基础课程-挑战3实验报告

    按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

    zhangjin7 ⋅ 昨天 ⋅ 0

    一起读书《深入浅出nodejs》-node模块机制

    node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

    小草先森 ⋅ 昨天 ⋅ 0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    返回顶部
    顶部