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小时内删除。