基于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:[email protected]
* 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
;
}
}
}
|