屏幕关闭时,Android加速度计无法正常工作

时间:2012-04-02 19:15:31

标签: android screen accelerometer sensor

我正在为我的计算机科学论文开发一个应用程序,我需要收集并记录加速度计数据。我需要一整天才能获得它,因此存在严重的电池限制(例如,我无法启动屏幕)。此外,这不是一个以市场为目标的应用程序,因此如果需要,可以进行一些严重的黑客攻击,甚至是低级C / C ++编码。

众所周知,在许多设备上,加速计事件的监听器在屏幕关闭时停止生成事件(关于此问题的一些链接:http://code.google.com/p/android/issues/detail?id=3708Accelerometer 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)

  1. 是否可以对加速计硬件进行低级访问(C / C ++方法)而无需注册到事件监听器?

  2. 还有其他解决方法或黑客吗?

  3. 任何拥有更新手机的人都可以测试一下固件3.0及以上版本是否仍然存在问题?

  4. [UPDATE]

    不幸的是,这似乎是一些手机的错误。我的答案中有更多细节。

6 个答案:

答案 0 :(得分:65)

基本上,这是我手机的问题。其他用户报告说,这也发生在他们的手机上,来自不同品牌但相同的Android版本。其他人完全没有问题 - 强烈表明这不是Android的库存版本的问题,而是来自每家公司的硬件驱动程序的实现。

我需要提供恒定的加速度计数据,并且不能让加密狗测量这些数据 - 我有一个带蓝牙和加速度计的Arduino,所以我可以实现这个解决方案。因此,我认为手机的临时解决方案是让屏幕开启(变暗)并忽略电池消耗。稍后,我将使用另一个在关闭屏幕的情况下运行的Android手机来执行电池使用测试。

有关错误的更多信息

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

我也用CyanogenMod RC7.2对它进行了测试,但它也没有用,因为加速度计驱动程序来自LG。

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

我发了一封电子邮件给LG P990的开发者,最后得到了一些具体的答案!对于像我这样经历Android问题的人来说,这可能会有很大的帮助。我写了以下问题

  

您好!我正在开发我的计算机科学论文,目前我   我从加速度计硬件中获取数据。截至目前,我发现了   当屏幕关闭时加速度计不发送事件,所以   即使我从我的一个程序中拿到一个唤醒锁,我也可以   验证我的程序是否仍在运行(通过LOGcat输出),但没有   加速计事件出来了。我必须调暗我的屏幕(我   不起,电池耗尽太快)开始接收   加速计事件再次发生。我也试过通过本地C访问它   代码,注册加速度计事件,但结果是   同样,加速度计没有抛出任何值,即使我是   旋转我的设备。所以我想知道我是否可以直接访问   硬件,使用本机代码,而无需注册到   监听器。这可能吗?如果是这样,你能不能再进一步   建议?我非常感谢任何帮助!马丁

我收到的回复是:

  亲爱的马丁,我们收到了Dev的回答。球队。他们说你   在手机屏幕关闭时无法获得加速度计事件。因为   HAL层没有实现sysFS路径来获取H / W事件,如   加速度计并没有公共API来获取事件。谢谢。最好   问候。 (肖恩金)

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

  

[...]我问了这个问题,因为我有一些朋友也有   具有相同姜饼版本的Android手机,但来自其他   手机品牌,其中一些人报告说他们收到了来自的手机   屏幕关闭时的加速度计。我读了一些   这个bug的论坛 - 我认为这是一个bug,因为当我获得一个   Wakelock我希望有一些处理正在进行 - 取决于   供应商为其手机实施的传感器驱动程序。是   有可能这些驱动程序可以更新或将这样   错误在某些时候得到纠正?这对我的帮助很大   正在进行的工作[...]

然后我收到了这个答案:

  

据我所知,来自Dev。团队,那​​不是bug。那是无限的   这款手机因为H / W架构。我们需要重新设计HAL   架构和设备驱动程序,以支持您的请求。但是,就像你一样   知道由于缺乏资源而太难了。我们正在努力   帮助您尽我们所能,但我们不能像我一样支持您的请求   提及。 (肖恩金)

所以他们显然知道这一点,但并没有试图纠正这一点,因为要么他们不认为这是一个错误 - 我仍然坚信这是一个合乎逻辑的缺陷 - 或者他们没有时间/资源来纠正它。

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

答案 1 :(得分:6)

我不确定这是否真的会对你有所帮助,但我找到了一个解决方法(不知道如果能帮助节省电池有多好)。

使用bash我有一个while循环cat /sys/devices/virtual/accelerometer/accelerometer/acc_file,当我通过电源按钮关闭屏幕时,输出继续,但被冻结。 (我的sshd在chroot中运行,因此能够看到它。)

然而,回应0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness。屏幕关闭,输出连续。

这是在SGH-T589W上,运行Android版本2.3.6。

答案 2 :(得分:2)

我遇到了类似的问题,三星Nexus使用其他系统服务运行 Android 4.0.2 ,在屏幕关闭时停止/暂停,即使获得了PARTIAL_WAKE_LOCK。我的解决方案是使用SCREEN_DIM_WAKE_LOCK,如:

 lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME);

将屏幕完全关闭会好得多,但至少这个解决方案有效,尽管如果我可以将SCREEN_DIM_WAKE_LOCK限制为只使用那些需要它的设备/操作系统,那就更好了。

答案 3 :(得分:2)

我应用了PARTIAL_WAKE_LOCK,它对我来说就像魅力一样。测试在OS 5.0,6.0& 7.0。这是我获取和释放唤醒锁的代码。小心它增加了电池的排水量,因此可以智能地获取和释放它。

import datetime as dt
import pandas as pd
series = pd.Series(list('abc'))
date = dt.datetime(2016, 10, 30, 0, 0)
series["Date_column"] =date
print("The date is {} and the type is {}".format(series["Date_column"], type(series["Date_column"])))
series["Date_column"] =date
print("The date is {} and the type is {}".format(series["Date_column"], type(series["Date_column"])))

参考:https://developer.android.com/training/scheduling/wakelock.html#cpu

我正在研究预测sdk,他使用设备传感器(加速度计/陀螺仪)数据并预测用户事件。我遇到了同样的问题。

答案 4 :(得分:0)

我讨厌让你失望,但是有些设备在睡眠模式下不会保持加速状态。有些人做,有些则不做。你可以检查商店里的任何计步器减肥应用程序,其中大多数明确说明这在某些设备上不起作用。

答案 5 :(得分:0)

如果部分唤醒锁定选项不适用于您的手机,则表示传感器的驱动程序已启用early_suspend

有两种选择。

1:禁用驱动程序中的EARLY_SUSPEND

2:在驱动程序级别添加可以enable / disable early_suspend功能的运行时标志。

离。 cat / sys / module / earlysuspend / sensor 1/0

IMO第二个选项应该从一开始就存在。