Android模拟计步器,即StepCounterSensor,StepDetectorS。
。。
最近各平台都推出⾏⾛计步相关的活动,⽆奈博主的烂⼿机只有Accelerometer,Light sensor,Proximity sensor,⽆法记录⾏⾛。于是翻查源码,模拟了⼀个。
要模拟计步器,必须修改android源码,我动到的在\frameworks\native\servises\sensorservice\ 这个⽬录下。其中SensorService.cpp的onFirstRef()是注册虚拟传感器的代码点。这⾥我参考了Gravitity sensor、Orientation sensor等的这类虚拟sensor的添加⽅法。因为这样实现⽐较简单,不然就要去hardware那⼀层添加,⿇烦度暴增。
⽽且因为我⼿机⾥连gyroscope也没有,所以只好想办法⽤Light sensor做了替换,以免条件判断不成⽴。如果你的⼿机已经有陀螺仪了,就不⽤替换Light相关的部分了。
[cpp]
1. void SensorService::onFirstRef()
2. {
3. ALOGD("");
4. SensorDevice& dev(SensorDevice::getInstance());
5.
6. if (dev.initCheck() == NO_ERROR) {
7. sensor_t const* list;
8. ssize_t count = SensorList(&list);
9. if (count > 0) {
10. ssize_t orientationIndex = -1;
11. bool hasGyro = false, hasAccel = false, hasMag = false;
12. uint32_t virtualSensorsNeeds =
13. (1< 0) {
14. batchingSupported = true;
15. break;
16. }
17. }
18.
19. if (batchingSupported) {
20. // Increase socket buffer size to a max of 100 KB for batching capabilities.
21. mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
22. } else {
23. mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
24. }
25.
26. // Compare the socketBufferSize value against the system limits and limit
27. // it to maxSystemSocketBufferSize if necessary.
28. FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
29. char line[128];
30. if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
31. line[sizeof(line) - 1] = '\0';
32. size_t maxSystemSocketBufferSize;
33. sscanf(line, "%zu", &maxSystemSocketBufferSize);
33. sscanf(line, "%zu", &maxSystemSocketBufferSize);
34. if (mSocketBufferSize > maxSystemSocketBufferSize) {
35. mSocketBufferSize = maxSystemSocketBufferSize;
36. }
37. }
38. if (fp) {
39. fclose(fp);
40. }
41.
42. mWakeLockAcquired = false;
43. mLooper = new Looper(false);
44. const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
45. mSensorEventBuffer = new sensors_event_t[minBufferSize];
46. mSensorEventScratch = new sensors_event_t[minBufferSize];
47. mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
48. mCurrentOperatingMode = NORMAL;
49.
50. mNextSensorRegIndex = 0;
51. for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
52. mLastNSensorRegistrations.push();
53. }
54.
55. mInitCheck = NO_ERROR;
56. mAckReceiver = new SensorEventAckReceiver(this);
57. mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
58. run("SensorService", PRIORITY_URGENT_DISPLAY);
59. }
60. }
61. }
void SensorService::onFirstRef()
{
ALOGD("");
SensorDevice& dev(SensorDevice::getInstance());
if (dev.initCheck() == NO_ERROR) {
sensor_t const* list;
ssize_t count = SensorList(&list);
if (count > 0) {
ssize_t orientationIndex = -1;
bool hasGyro = false, hasAccel = false, hasMag = false;
uint32_t virtualSensorsNeeds =
(1< 0) {
batchingSupported = true;
break;
}
}
if (batchingSupported) {
/
/ Increase socket buffer size to a max of 100 KB for batching capabilities.
mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
} else {
mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
}
// Compare the socketBufferSize value against the system limits and limit
// it to maxSystemSocketBufferSize if necessary.
FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
char line[128];
if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
line[sizeof(line) - 1] = '\0';
size_t maxSystemSocketBufferSize;
sscanf(line, "%zu", &maxSystemSocketBufferSize);
android模拟点击if (mSocketBufferSize > maxSystemSocketBufferSize) {
mSocketBufferSize = maxSystemSocketBufferSize;
}
}
if (fp) {
fclose(fp);
}
mWakeLockAcquired = false;
mLooper = new Looper(false);
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
mCurrentOperatingMode = NORMAL;
mNextSensorRegIndex = 0;
for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
mLastNSensorRegistrations.push();
}
mInitCheck = NO_ERROR;
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
run("SensorService", PRIORITY_URGENT_DISPLAY);
}
}
}
另外在SensorFusion.cpp的构造函数⾥也要将gyro替换成light,不然没有陀螺仪的话,Fusion没办法初始化成功。
// 2016-12-22 morrowindxie replaced by light sensor if no gyroscope.
//if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
if (list[i].type == SENSOR_TYPE_LIGHT) {
后来发现替换成Light倒有个好处是能借⽤它来⾃动判断⽩天⿊夜。例如Lux⼩于多少认为在⿊暗环境下,就停⽌记步等。不过我的样例⾥暂时还没⽤到它,⽽只是采⽤了固定的算法:每秒钟记⼀步,每
天根据设定好的开始时间跟结束时间⽚,累计总的步数这样。
最后贴上StepSensor.cpp和.h的代码,这两个⽂件都是新增的。这个⽂件⾥⾯包含了两个sensor类,⼀个是StepCounter,⼀个是StepDetector。StepCounter根据官⽅定义,每次⼿机重启后归零,写的字段是u64.step_counter,为开机以来的总步数。StepDetector根据定义,检测到⾛步的时候,data[0]置1,否则data[0]置0,然后上报消息。
我的样例⾥,⾛路的时间,定死在代码⾥了(后续想弄个配置⽂件放到sd卡⾥,代码读取配置⽂件来加载⾛路的时间段,更加灵活⼀点),简单模拟了⽩天的随机⾛路(主要是根据tm结构中的wday跟yday来做简单的随机,具体算法见代码),这样看起来⽐较真实点,不然每天固定时间开始运动,步数都⼀样多那也太假了。当然你愿意,改成所有时间都在⾛路,每秒⾛3步也⽆不可,不过⼩⼼被⼀些平台抓到作弊给封号了,哈哈。
StepSensor.cpp
[cpp]
1. /*
2. * Copyright (C) 2016 Morrowind.Xie
3. *
4. * This program is free software; you can redistribute it and/or modify it
5. * under the terms of the GNU General Public License as published by the
6. * Free Software Foundation; either version 2, or (at your option) any
7. * later version.
8. *
9. * This program is distributed in the hope that it will be useful, but
10. * WITHOUT ANY WARRANTY; without even the implied warranty of
11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12. * General Public License for more details.
13. *
14. * This project is an adaptation of the original fbvncserver for the iPAQ
15. * and Zaurus.
16. */
17.
18. #include
19. #include
20. #include
21.
22. #include
23.
24. #include
25.
26. #include "StepSensor.h"
27. #include "SensorDevice.h"
28. #include "SensorFusion.h"
29.
30. // Rule sample: 19:xx:yy ~ 21:yy:xx
31. // Which xx = (tm_wday+3)^2 % 60, yy = (tm_yday+3)^2 % 60.
32. // To get a random step count for each day.
33. namespace android {
34. // ---------------------------------------------------------------------------
35.
36. StepCounterSensor::StepCounterSensor()
37. : mSensorDevice(SensorDevice::getInstance()),
38. mSensorFusion(SensorFusion::getInstance())
39. {
40. ALOGD("");
41. time_t timeNow;
42. time(&timeNow);
43. struct tm *localTimeNow = localtime(&timeNow);
44. mLastReportTime = *localTimeNow;
45. mStepCount = 0;
46. }
47.
48. typedef struct {
49. int startHour;
50. int endHour;
51. } WALKING;
52. static WALKING walkingTimes[] = {
53. {6, 7}, {8, 11}, {14, 16}, {19, 20}
54. };
55. static int nbrSegments = sizeof(walkingTimes)/sizeof(WALKING);
56. static int countDailyCumulateSteps(struct tm *now) {
57. int walkingSeconds = 0;
58. int xx = (now->tm_wday+3)*(now->tm_wday+3)%60;
59. int yy = (now->tm_yday+3)*(now->tm_yday+3)%60;
60. int secStart, secEnd, secNow;
61. for(int i=0; itm_hour*60 + now->tm_min)*60 + now->tm_sec;
62. if(secEnd < secNow) {
63. walkingSeconds += (secEnd-secStart);
64. } else if(secStart < secNow) {
65. walkingSeconds += (secNow-secStart);
66. }
67. }
68. return walkingSeconds;
69. }
70.
71. static int countPeriodSteps(struct tm *beginTime, struct tm *endTime) {
72. int beginSteps = countDailyCumulateSteps(beginTime);
73. int endSteps = countDailyCumulateSteps(endTime);
74. int steps = 0;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论