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

时间:2017-10-19 21:35:21

标签: android sensor runnable android-sensors

我每隔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的一部分,所以我不确定为什么没有注册?

3 个答案:

答案 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)

您可以使用TimerTimerTask来实现此目的。只是一个例子。

 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中使用它们。