我正在为我的计算机科学论文开发一个应用程序,我需要收集并记录加速度计数据。我需要一整天才能获得它,因此存在严重的电池限制(例如,我无法启动屏幕)。此外,这不是一个以市场为目标的应用程序,因此如果需要,可以进行一些严重的黑客攻击,甚至是低级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及以上版本是否仍然存在问题?
[UPDATE]
不幸的是,这似乎是一些手机的错误。我的答案中有更多细节。
答案 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第二个选项应该从一开始就存在。