2012-04-02 63 views
62

我正在为计算机科学的最终论文开发一个应用程序,而且我需要收集并记录加速计数据。我需要购买一整天,因此存在严重的电池限制(例如,我无法离开屏幕)。另外,这不是一个针对市场的应用程序,因此如果需要,进行一些严重的黑客攻击,即使是低级的C/C++编码也是可以接受的。当屏幕关闭时Android加速度计不工作

众所周知,在许多设备上,加速计事件监听器在屏幕熄灭时停止生成事件(有关此问题的一些链接: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。关于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或更高版本中?

[更新]

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

+1

嗨。我刚刚用我的HTC Sensation(ICS)测试了这个问题。加速度计和磁场传感器都在屏幕关闭的情况下保持报告值。另外,您是否检查了评论[46](http://code.google.com/p/android/issues/detail?id=3708)中描述的解决方法? – Renard 2012-04-02 20:10:07

+0

谢谢你的反馈Renard。 关于评论46,我也试过了,它和运行定期取消注册/注册事件监听器的线程几乎是一样的。但是对于我的设备,每次关闭显示器时我只能获得加速度计的固定值.. 也感谢您在ICS上进行测试...它很高兴知道它适用于它应该,可悲的是没有ICS的LG P990了呢=/ – martin 2012-04-03 01:47:50

+1

可能会有用尝试解决问题从另一方 - 获取屏幕锁定,但同时将屏幕亮度降至零以节省电池电量?当然,使用电源按钮关闭屏幕时不起作用,但在这种情况下,您可以尝试唤醒设备以防止屏幕锁定。 – 2012-04-25 20:21:33

回答

61

基本上,这是我的手机有问题。其他用户也报道过这种情况也会发生在他们的手机上,这些手机来自不同的品牌,但Android版本相同其他人完全没有问题 - 强烈表明这不是Android的股票版本的问题,而是来自于每个公司的硬件驱动程序的实现。

我需要不断的加速计数据传输,不能有一个加密狗测量这个数据,我 - 我有蓝牙和加速度计一个Arduino,所以我可以实现这个解决方案。所以我决定为我的手机设置临时解决方案,让屏幕亮起(变暗)并忽略电池消耗。稍后,我将使用另一个与屏幕关闭的Android手机进行电池使用测试。关于此bug

更多信息

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

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

电子邮件与LG

的人力资源管理部门交换我发了一封邮件到LG P990的开发商终于得到了一些具体的答案!对于像我这样遇到Android这些问题的人来说,这可能会有很大的帮助。我写了下面的问题

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

对于我收到此回应:

亲爱的马丁,我们从开发得到的回答。球队。他们表示,当您的手机屏幕关闭时,您无法获取加速计事件 。因为 HAL层没有实现sysfs路径来获得H/W事件,例如 加速计,并且没有公共API来获取事件。谢谢。最好的 关心。 (肖恩金)

然后我发了一封邮件退回,除其他外说,我收购唤醒锁时,认为这是一个错误,因为人都应该有所有的硬件访问:

[...]我问这个问题,因为我有一些朋友也有 Android手机使用相同的姜饼版本,但是从其他 手机品牌,其中一些报告说,他们收到来自 加速度计的事件,当屏幕被关闭。我读了一些 论坛,这个错误 - 我认为这是一个错误,因为当我获得 激活锁定我希望有一些处理事情 - 取决于 传感器驱动程序的供应商实现了自己的手机。 有没有可能更新这些驱动程序,或者这个 错误在某些时候会被纠正?这将帮助我极大我 正在进行的工作[...]

然后,我收到这样的回答:

在从开发我的知识。团队,这不是bug。这是因为H/W架构,这款手机的无限 。我们需要重新设计HAL 架构和设备驱动程序以支持您的请求。但是,由于缺乏资源,你知道这太难了。我们正在努力帮助您尽我们所能,但我们无法支持您的要求,因为我提到了 。 (肖恩金)

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

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

+2

感谢martin提供了非常完整的信息。我们真正需要的是一个列表,说明哪些手机在屏幕上支持加速计事件,因为人们在购买之前可能需要这些信息(像我 - 我需要这样)。也许一个维基,人们可以测试他们的手机并更新列表。有没有像这样的任何列表? – Fletch 2012-06-01 09:21:01

+8

好的,我做了一个清单:http://www.saltwebsites.com/2012/android-accelerometers-screen-off – Fletch 2012-06-26 10:35:37

+2

令人惊叹的,真正全面的答案。会给出不止一个大拇指:)在某种程度上,您可以通过侦听SCREEN_OFF和SCREEN_ON事件来解决问题,获取新的唤醒锁并重新启动加速度计服务。但是,它只能在一些手机上使用。 – LambergaR 2012-07-16 22:40:55

0

我不想让你失望,但是有些设备在睡眠模式下不会让加速度计继续工作。有些是,其他则不是。你可以检查商店里的任何计步器减肥应用程序,大多数应用程序明确声明这不适用于某些设备。

2

我碰到与三星Nexus采用其它系统的服务,停止/暂停,而屏幕是关闭的,即使一个PARTIAL_WAKE_LOCK获取运行的Android 4.0.2类似的问题。我的解决办法是使用一个SCREEN_DIM_WAKE_LOCK为:

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

这将是更好的选择有屏幕完全关闭,但至少该解决方案的工作,尽管它会更好,如果我能限制使用SCREEN_DIM_WAKE_LOCK只那些需要它的设备/操作系统。

6

我不知道这是否会真正帮助你,但我发现周围的工作(不知道怎么好,如果将有助于节电虽然)。

使用bash我有一个while循环捕获/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版本。

+0

你在代码中完成了这个吗? – baash05 2013-07-10 12:02:24

+0

唉!很好玩,不要想到bash脚本。我想我会尽量在后面尝试,尽管我很久以前就已经完成了这项工作.. 感谢您的输入! – martin 2013-07-15 16:53:25

0

如果局部唤醒锁选项不可用您的手机就意味着对传感器的驱动程序有early_suspend启用。

有两种选择。

1:禁用EARLY_SUSPEND在驾驶员

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

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

IMO第二个选项应该从那开始。

2

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

public void acquireWakeLock() { 
    final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 
    releaseWakeLock(); 
    //Acquire new wake lock 
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK"); 
    mWakeLock.acquire(); 
} 

public void releaseWakeLock() { 
    if (mWakeLock != null && mWakeLock.isHeld()) { 
     mWakeLock.release(); 
     mWakeLock = null; 
    } 
} 

编号:https://developer.android.com/training/scheduling/wakelock.html#cpu

我工作的一个预测SDK,谁使用设备传感器(加速度计/陀螺仪)数据和预测用户的事件。我遇到了同样的问题。