当屏幕closures时,Android加速计不工作
我正在为计算机科学的最终论文开发一个应用程序,我需要收集和logging加速计数据。 我需要整整一天的时间,所以有严重的电池限制(例如,我不能离开屏幕)。 此外,这不是一个市场针对性的应用程序,所以如果需要的话,做一些严重的黑客攻击,甚至是低级的C / C ++编码是相当可接受的。
众所周知,在许多设备上,加速度计事件的侦听器在屏幕熄灭时停止生成事件(有关此问题的一些链接: http : //code.google.com/p/android/issues/detail? id = 3708 , Accelerometer在Droid / Nexus One屏幕closures的情况下停止提供样本,即使使用WakeLock也是如此 )。 我彻底search了一些替代品,其中一些包括变通办法,不适用于我的设备(LG P990,股票ROM)。
那么会发生什么呢:当你在一个服务中注册一个android加速度计传感器的事件监听器时,它会正常工作,直到屏幕closures。 我已经尝试在IntentService上的Service上注册eventListener,试图获取WakeLocks。 关于wakelocks,我可以validation服务仍在运行看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及以上版本中持续存在,那么是否可以使用更新的电话进行testing?
[UPDATE]
不幸的是,这似乎是一些手机的错误。 更多的细节在我的答案。
基本上,这是我的手机的问题。 其他用户已经报道,这也发生在他们的手机,从不同的品牌,但相同的Android版本。 其他人完全没有问题 – 强烈地表明这不是Android的股票版本的问题,而是来自于每个公司的硬件驱动程序的实现。
我需要传递恒定的加速度计数据,并且不能有encryption狗测量这个数据 – 我有一个带蓝牙和加速度计的Arduino,所以我可以实现这个解决scheme。 所以我决定,我的手机的临时解决scheme是让屏幕(暗淡),而忽略电池消耗。 稍后,我将使用另一个与屏幕closures的Android手机进行电池使用testing。
有关该错误的更多信息
我已经研究了一些其他的Android用户的报告,我想也许我明白发生了什么事。 具有手机传感器驱动程序的libsensors.so库不是由Google开发的,而是由每个手机厂商开发的 – 当然,因为每个手机都有自己特定的硬件。 谷歌只提供一个C头文件,以便开发人员知道他们必须执行什么。 在这些驱动程序的一些实现中,开发人员只需在屏幕closures时closures加速度计,从而防止传感器事件侦听器接收新事件。
我也用CyanogenMod RC7.2testing了这个,但是它也没有工作,因为加速度计驱动程序是LG原创的。
与LG人力资源部门交换电子邮件
我给LG P990的开发者发了一封电子邮件,最后得到了一些具体的答案! 这可能对像我这样的Android用户遇到这些问题的人有很大的帮助。 我写了下面的问题
你好! 我正在开发我的计算机科学的论文,目前我正在从加速计硬件中获取数据。 到目前为止,我发现加速度计不能在屏幕closures的时候发送事件,所以即使从我的一个程序中抓取一个wakelock,我也可以validation我的程序仍在运行(通过LOGcat输出),但是没有加速度计事件出来。 我必须调暗我的屏幕(我无法承受,电池消耗太快),以再次开始接收加速计事件。 我也尝试通过本机C代码访问它,注册加速器事件,但结果是一样的,加速度计没有抛出任何值,即使我正在旋转我的设备。 所以我想知道是否可以用本地代码直接访问硬件,而不必注册到监听器。 这可能吗? 如果是这样,你可以提供一些进一步的build议吗? 我非常感谢任何帮助! 马丁
对于我收到的回复:
亲爱的马丁,我们收到了Dev的回答。 球队。 他们说,当你的手机屏幕closures时,你不能得到加速计事件。 由于HAL层没有实现sysfspath来获得像加速度计这样的H / W事件,并且没有公共API来获取事件。 谢谢。 最好的祝福。 (肖恩·金)
然后,我发回了一封电子邮件,其中说,我认为这是一个错误,因为在获取唤醒锁时,应该可以访问所有的硬件:
[…]我问这个问题,因为我有一些朋友,也有Android手机姜饼版本相同,但从其他手机品牌,其中一些人报告,他们收到来自加速度计事件,当屏幕closures。 我在一些论坛上读到这个bug – 我认为它是一个错误,因为当我获得一个Wakelock时,我希望有一些处理正在进行 – 取决于供应商为他们的手机实现的传感器驱动程序。 有没有可能更新这些驱动程序,或者在某个时候纠正这个错误? 这对我正在进行的工作将有极大的帮助[…]
然后我收到了这个答案:
从我的知识Dev。 团队,这不是bug。 由于H / W架构,这是一款无限的手机。 我们需要重新deviseHAL体系结构和设备驱动程序来支持您的请求。 但是,如你所知,由于缺乏资源,这太困难了。 我们正在竭尽全力帮助您,但我们无法支持您提出的要求。 (肖恩·金)
所以他们显然知道这一点,但是并没有试图纠正这个问题,因为他们不认为这是一个错误 – 我仍然坚信这是一个逻辑错误 – 或者他们没有时间/资源来纠正错误。
底线如果您的手机没有在closures屏幕的情况下发送加速计事件,请尝试更新您的固件。 如果这个问题没有解决,而且你真的想做一些严重的黑客攻击,那就重新实现你的硬件层 – 提示:这可能与libsensors.so有关。
我不知道这是否会帮助你,但我find了一个解决办法(不知道如何将有助于节约电池)。
使用bash我有一个while循环cat-ing /sys/devices/virtual/accelerometer/accelerometer/acc_file
,当我通过电源buttonclosures屏幕时,输出继续,但是被冻结。 (我曾经在一个chroot中运行,因此能够看到它。)
但是,在回显0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness
。 屏幕closures,输出连续。
这是运行Android 2.3.6版本的SGH-T589W。
我已经遇到类似的问题,运行Android 4.0.2的三星Nexus使用其他系统服务,停止/暂停屏幕closures,即使PARTIAL_WAKE_LOCK
被收购。 我的解决scheme是使用SCREEN_DIM_WAKE_LOCK
如下所示:
lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME);
将屏幕完全closures会好得多,但至less这个解决scheme可以工作,但如果我可以限制SCREEN_DIM_WAKE_LOCK
仅限于那些需要它的设备/操作系统,那将会更好。
我应用了PARTIAL_WAKE_LOCK,它对我来说很有魅力。 testingOS 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,他使用设备传感器(加速度计/陀螺仪)数据并预测用户事件。 我遇到了同样的问题。
我讨厌让你失望,但是有些设备在睡眠模式下不能保持加速器的开启。 有些是做的,有些则没有。 你可以检查任何计步器减肥应用程序商店大多数明确指出,这将无法在一些设备上工作。
如果部分唤醒locking选项不适用于您的手机,则表示传感器的驱动程序已启用early_suspend
。
有两个选项。
1:在驱动程序中禁用EARLY_SUSPEND
2:添加一个运行时间标志,可以在驱动程序级别enable
/ disable early_suspend
function。
恩。 cat / sys / module / earlysuspend / sensor 1/0
海事组织的第二个select应该从一开始就在那里。