屏幕关闭时Android加速度计不工作

我正在开发一个关于计算机科学的最终论文的应用程序,我需要收集和记录加速度计数据。我需要获得一整天的时间,所以有严重的电池限制(例如,我不能离开屏幕)。此外,这不是一个市场针对性的应用程序,所以它是完全可以接受的做一些严重的黑客,甚至低级C/C++编码,如果需要。

众所周知,在许多设备上,加速度计事件的监听器在屏幕关闭时停止生成事件(关于这个问题的一些链接:http://code.google.com/p/android/issues/detail?id=3708,Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock)。我已经彻底搜索了一些替代品,其中一些包括不工作,我的设备(LG P990,股票ROM)的解决方法。

所以发生了什么是这样的:
当您在服务中为Android加速度传感器注册事件侦听器时,它会正常工作,直到屏幕关闭。我已经尝试在IntentService上的服务上注册eventListener,试图获取WakeLocks。关于唤醒锁,我可以验证服务仍在运行,观察LOGcat输出,但似乎加速度计被置于睡眠模式。在一些链接中提出的解决方法之一是使用IntentService的线程定期地注销和重新注册事件侦听器,如下面的代码片段所示

synchronized private static PowerManager.WakeLock getLock(Context context) {
    if (lockStatic==null) {
        PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);

        lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME);
        lockStatic.setReferenceCounted(true);
    }

    return(lockStatic);
}

@Override
protected void onHandleIntent(Intent intent) {

     sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
     sensorManager.unregisterListener(this);
     sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);


    synchronized (this) {
        boolean run = true;
        while (run){
            try {
                wait(1000);
                getLock(AccelerometerService.this).acquire();
                sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
                sensorManager.unregisterListener(this);
                sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
                Log.d("Accelerometer service", "tick!");

            } catch (Exception e) {
                run = false;
                Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage());


            }
        }
    }       
}


@Override
public void onSensorChanged(SensorEvent event) {
    Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," +  event.values[2]);
}

这确实使每次我们注销/注册监听器时调用onSensorChange。问题是,接收的事件包含总是相同的值,不管我摇晃设备。

所以,基本上我的问题是:(与我一起,我几乎完成:P)

>是否可以对加速度计硬件进行低级访问(C/C++方法)而不注册到事件侦听器?
>有没有其他解决方法或黑客?
>任何人都可以使用更新的电话测试如果固件3.0及以上的问题仍然存在?

[更新]

不幸的是,它似乎是一些bug与一些手机。更多细节在我的答案。

最佳答案
基本上,这是一个问题,我的手机。其他用户报告这也发生在他们的手机,从不同的品牌,但相同的Android版本。其他人没有任何问题 – 强烈表明这不是一个问题与股票版本的Android,但从每个公司的实施他们的硬件驱动程序。

我需要恒定的加速度计数据交付,不能有加密狗测量这个数据 – 我有一个Arduino的蓝牙和加速度计,所以我可以实现这个解决方案。所以我决定,我的手机的临时解决方案是让屏幕打开(调暗),忽略电池消耗。后来我将使用另一个Android手机,屏幕关闭工作电池使用测试。

关于错误的更多信息

我已经研究了更多,发现其他Android用户的报告,我想也许我明白发生了什么。图书馆libsensors.so,它有手机传感器的驱动程序不是由谷歌开发的,但是每个手机供应商 – 当然,因为每个手机有自己的特定硬件。 Google只提供一个C头文件,以便开发人员知道他们必须实现什么。在这些驱动程序的某些实现中,开发人员只需在屏幕关闭时关闭加速度计,从而防止传感器事件侦听器接收新的事件。

我也用CyanogenMod RC7.2测试这个,但它没有工作,因为加速度计驱动程序是从LG原来的。

与LG人力资源部门交流的电子邮件

我给LG P990的开发者发了一封电子邮件,终于得到了一些具体的答案!这可能是一些像我这样的人在Android上遇到这些问题很大的帮助。我写了以下问题

Hello! I am developing my thesis in computer science and currently I
am fetching data from accelerometer hardware. As of now, I found out
that the accelerometers do not send events when the screen is off, so
even when I grab a wakelock from within one of my programs, I can
verify that my program is still running (through LOGcat output) but no
accelerometer event comes out. I have to dim my screen on (which I
cannot afford, the battery drains too fast) to start receiving
accelerometer events again. I also tried accessing it through native C
code, registering on the accelerometer events but the result was the
same, the accelerometer did not throw any values, even though I was
rotating my device. So I was wondering if I could have direct access
to the hardware, with native code, without having to register to a
listener. Is this possible? If so, could you kindly give some further
advice? I would appreciate very much any help! Martin

对于我收到这个回应:

Dear Martin, We received the answer from Dev. Team. They said that you
can’t get accelerometer event while your phone screen is off. Because
HAL layer didn’t implement sysFS path to get H/W event such as
accelerometer and there is no public API to get event. Thank you. Best
Regards. (Sean Kim)

然后,我发回了一封电子邮件,其中包括,我认为这是一个错误,因为当获取唤醒锁时,应该有权访问所有的硬件:

[…] I asked this question because I have some friends that also have
Android phones with the same gingerbread version but from other
cellphone brands, and some of them reported they receive events from
the accelerometers when the screen is turned off. I read on some
forums that this bug – I consider it a bug, since when I acquire a
Wakelock I would expect to have some processing going on – depends on
the sensor drivers that the vendors implement for their cellphones. Is
there any possibility that these drivers can be updated or will this
bug be corrected at some point? This would help me enormously with my
ongoing work […]

然后我收到这个答案:

In my knowledge from Dev. Team, That isn’t bug. That is a limitless of
this phone because of H/W architecture. We need to redesign the HAL
architecture and device driver to support your request. But, as you
know that is too difficult due to lack of resource. We are trying to
help you with our all efforts but we cannot support your request as I
mentioned. (Sean Kim)

所以他们显然知道这一点,但不是试图纠正这一点,因为他们不认为这是一个错误 – 我仍然强烈认为是一个逻辑缺陷 – 或者他们没有时间/资源来纠正它。

底线
如果您的手机在屏幕关闭时不发送加速计事件,请尝试更新固件。如果这不解决,你真的想做一些严重的黑客,重新实现你的硬件层 – 提示:这可能是与libsensors.so有关。

转载注明原文:屏幕关闭时Android加速度计不工作 - 代码日志