每隔1/10秒获取传感器数据



我正在尝试每隔十分之一秒记录Android传感器数据(加速度计、陀螺仪)。使用安卓提供的值(AI、GAME、NORMAL)或用户定义的值(例如100000微秒)绝对没有区别,onSensorChanged每1/100秒触发一次。这对电池寿命和日志文件的大小(每天要记录6000万个事件)都不利。

我可以使用一个简单的循环来实现它,只需丢弃9/10值,但这意味着您仍然在注册每个事件,只是没有将其写入文件,这似乎并不理想。

我的下一个想法是每隔1/10秒使用一次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秒运行一次,但整个可运行程序在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在可运行程序运行时不会被调用,但如果我删除:

unregisterAccel();

从Runnable,它返回到每1/100秒接收一次数据。

我在这里碰壁了,我想不出任何其他方法来获得每10秒一次的读数。

请注意,这是一款将全天候在后台运行的应用程序,所以我正在尽我所能将电池消耗降至最低,我真的很希望这能奏效,因为注册然后注销传感器似乎是最好的选择,但我想这可能只需要超过1/10秒的时间?

如果有人能发现我的代码有问题,那就太棒了!

编辑:好的,在进一步的测试中,我想我一定误解了什么。我尝试将thread.sleep延长到10秒,但仍然没有得到OnSensorChanged事件,即使传感器仍然注册。这让我很困惑,因为唯一应该休眠的线程是可运行的,传感器已经注册,而OnSensorChanged不是可运行的一部分,所以我不确定为什么什么都没有注册?

您可以使用全局布尔值(我知道…)来维护状态。类似于:

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
}
}

您为采样率输入的默认值或值运行良好。我在几个设备上进行了测试。你的手机可能有问题。你也可以用安卓工作室和它的虚拟传感器测试传感器。

要从另一个线程获取值,您应该使用SensorManager.registerListener(listener, sensor, samplingPeriodUs, handler);方法,在线程内注册它们将没有帮助,因为SensorManager的处理程序是UI线程上的处理程序。您可以参考此链接在单独的线程中实现寄存器传感器。

您可以为此目的使用Timer和TimerTask。只是一个例子。

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);

100毫秒是你的周期。

Timer的方法时间表如下:

void schedule (TimerTask task, 
long delay, 
long period)

有关详细信息,请参阅Timer文档。

您应该将传感器值连续存储在Sensorchanged中的各个变量中,并在TimerTask中使用它们(每100毫秒触发一次)。

最新更新