基於Android的計步器(Pedometer)的講解(四)——後臺記步

  • 基於Android的計步器(Pedometer)的講解(四)——後臺記步php

  • 2015-01-07      58 個評論    來源:a296777513的專欄   html

  • 收藏    我要投稿java

  • 今天先不說Pedometer(計步器)項目UI方面的了,今天講一個基於重力加速度的記步功能傳感器(Sensor),而後android

    在後臺開啓記步。git

     

    計步器(Pedometer)整個項目的源代碼,感興趣的朋友能夠下載來看看(記得幫小弟在github打個星~)github

     

    先上幾張效果圖:(效果和上一篇講到的CircleBar很是的類似,由於記步功能在後臺)算法

    \\

    如圖所示,能根據你的一些基本參數,來記步。有一個缺點,由於這個是根據感應加速度來計算是否走一步,因此你在原地晃手機,也會記步,不過正常的走路仍是挺準確的。安全

    首先給出StepDetector類的代碼:app

     

    ?dom

    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 ;
             }
             
         }
     
    }
相關文章
相關標籤/搜索