我每隔1/10秒尝试记录Android传感器数据(Accelerometer,Gyro)。使用Android提供的值(AI,GAME,NORMAL)或用户定义的值(例如100000微秒)完全没有区别,onSensorChanged每1/100秒触发一次。这对电池寿命和记录文件的大小都很不利(每天记录6000万个事件)。
我可以使用一个简单的循环使其工作,并简单地丢弃9/10值,但这意味着你仍在注册每个事件,只是不将它写入文件,这似乎并不理想。
我的下一个想法是每隔1/10秒使用一个Runnable,这样只会得到一个传感器,而不是两个传感器。
我的下一个想法是为每个传感器设置一个runnable,并在runnable中注册并取消注册每个传感器:
public void registerAccel(){
Log.d(TAG, "registerAccel: on");
sensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
public void unregisterAccel(){
Log.d(TAG, "unregisterAccel: off");
sensorManager.unregisterListener(this, mAccelerometer);
}
private final Runnable processAccel = new Runnable() {
@Override
public void run() {
Log.d(TAG, "run: AccelStart");
registerAccel();
mHandler.postDelayed(this, interval);
unregisterAccel();
}
};
这没有产生传感器读数,但我注意到即使可运行的每1/10秒运行一次,整个Runnable也在1/1000秒完成,但我可能太快而无法注册传感器。所以我加了一个睡眠:
private final Runnable processAccel = new Runnable() {
@Override
public void run() {
Log.d(TAG, "run: AccelStart");
registerAccel();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.postDelayed(this, interval);
unregisterAccel();
}
};
这使Runnable保持打开1/10秒,但我仍然没有从传感器接收任何数据?基本上onSensorChanged在runnable运行时没有被调用,但如果我删除了:
unregisterAccel();
来自Runnable的,它每1/100秒返回一次接收数据。
我在这里碰壁,我无法想到任何其他方式每隔十分钟读一次。
请注意,这是一款将在后台全天候运行的应用程序,所以我尽我所能尽量减少电量消耗,我真的希望这会有效,因为注册然后取消注册传感器似乎最好的选择,但我想这可能需要超过1/10秒才能这样做?
如果有人发现我的代码有问题,那就太棒了!
编辑: 好的进一步测试,我想我一定是误会了。我尝试将thread.sleep扩展到10秒,并且仍然没有得到OnSensorChanged事件,即使传感器仍然已注册。这让我很困惑,因为应该睡觉的唯一线程是runnable,传感器是注册的,OnSensorChanged不是Runnable的一部分,所以我不确定为什么没有注册?
答案 0 :(得分:1)
您可以使用全局布尔值(我知道...)来维护状态。类似的东西:
boolean checkSensor = false;
@Override
public void onResume() {
super.onResume();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
checkSensor = true;
}
}, 100);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (checkSensor) {
checkSensor = false;
// do your stuff
}
}
答案 1 :(得分:0)
您为抽样率输入的默认值或值效果很好。我在几台设备上测试过它。这可能与您的手机有关。您还可以使用Android Studio及其虚拟传感器测试传感器。
要从另一个线程获取值,您应该使用SensorManager.registerListener(listener, sensor, samplingPeriodUs, handler);
方法,在线程中注册它们不会有帮助,因为SensorManager的处理程序是UI线程上的处理程序。您可以参考此链接来实施register sensor in separate thread。
答案 2 :(得分:0)
您可以使用Timer和TimerTask来实现此目的。只是一个例子。
try:
return interv
finally:
if interv is not NULL:
free(interv)
这段时间是100毫秒。
计时器的方法时间表如下所示:
Timer timer_sensor = new Timer();
TimerTask task_process_sensor = new TimerTask() {
public void run() {
//perform your action here
}
};
timer_sensor.schedule(task_process_sensor, 0, 100);
有关详细信息,请参阅Timer文档。
您应该将传感器值连续地存储在void schedule (TimerTask task,
long delay,
long period)
中的相应变量中,并在每100毫秒触发一次时在TimerTask中使用它们。