屏幕关闭时,Android加速度计不起作用


70

我正在为我的计算机科学毕业论文开发一个应用程序,我需要收集和记录加速度计数据。我需要整整一整天才购买它,所以电池电量受到严重限制(例如,我无法打开屏幕)。而且,这不是面向市场的应用程序,因此,如果需要的话,进行一些严重的黑客入侵甚至是低级C / C ++编码也是可以接受的。

众所周知,在许多设备上,当屏幕关闭时,加速度计事件的侦听器会停止生成事件(有关此问题的一些链接:http : //code.google.com/p/android/issues/detail? id = 3708加速度计当屏幕在Droid / Nexus One上关闭时,即使有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及更高版本是否仍然存在该问题?

[更新]

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


1
你好 我刚刚使用HTC Sensation(ICS)测试了该问题。加速度计和磁场传感器都在屏幕关闭的情况下保持报告值。另外,您是否检查了注释46中所述的解决方法?
雷纳德

1
尝试从另一侧解决问题可能会很有用-获取屏幕锁定,但同时将屏幕的亮度降低到零以节省电池?当然,使用电源按钮关闭屏幕时不起作用,但是在这种情况下,您可以尝试唤醒设备以防止屏幕锁定。
Andrey Starodubtsev

1
我最近在多个不同型号的android上记录了加速度计和磁力计,却从未遇到过这个问题。我的型号包括一些HTC和一个Samsung Captivate,所以我猜选择范围不是很多。但是,也许这是您的命题,那么至少值得与您的好友临时交易电话以获取日志。您可能还考虑使用DIM屏幕唤醒锁运行并减少记录频率,将手机一次睡眠5分钟,然后定期唤醒以获取一些样本。为此,请使用AlarmManager和BroadcastReciever。
mwengler

3
马丁,我认为您已经回答了自己的问题,因此您应该创建并接受该问题的答案,并将所有发现都纳入其中。
雷纳德

1
是否可以选择使用独立的加速度计,例如Shimmer Research生产的通过蓝牙发送数据的加速度计?您甚至可以轻松地将自己的固件写入并刷新到这些固件:shimmer-research.com我本人已经与他们合作,并且它们可以工作(并且可以与Android一起工作)-尽管您必须研究其电池寿命。
Thomas Dignan '04

Answers:


71

基本上,这是我的手机有问题。其他用户报告说,使用不同品牌但使用相同Android版本的手机也会发生这种情况。其他人完全没有问题-强烈表明这不是android的普通版本,而是每个公司的硬件驱动程序实现问题。

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

有关该错误的更多信息

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

我也使用CyanogenMod RC7.2对此进行了测试,但是它也不起作用,因为加速度计驱动程序是LG最初提供的。

与LG HR部门交换的电子邮件

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

你好!我正在研究计算机科学方面的论文,目前正在从加速度计硬件中获取数据。到目前为止,我发现在屏幕关闭时加速度计不会发送事件,因此,即使我从其中一个程序中获取了唤醒锁,也可以验证程序是否仍在运行(通过LOGcat输出),但是加速度计事件出来了。我必须调暗屏幕(我负担不起,电池电量消耗得太快),才能再次开始接收加速度计事件。我还尝试通过本机C代码访问它,并在加速度计事件上注册,但是结果是一样的,即使我旋转设备,加速度计也不会抛出任何值。因此,我想知道是否可以通过本机代码直接访问硬件,而不必注册到侦听器。这可能吗?如果是这样,请您再提出一些建议?我将不胜感激!马丁

对于我收到的此答复:

亲爱的马丁:我们收到了开发人员的答复。球队。他们说,手机屏幕关闭时,您无法获得加速度计事件。因为HAL层未实现sysFS路径来获取诸如加速度计之类的硬件事件,所以没有公共API来获取事件。谢谢。最好的祝福。(Sean Kim)

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

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

然后我收到了这个答案:

根据开发人员的知识。团队,那​​不是虫子。由于H / W架构,这对这款手机来说是无限的。我们需要重新设计HAL架构和设备驱动程序,以支持您的请求。但是,正如您所知,由于缺乏资源,这太困难了。我们正在竭尽全力为您提供帮助,但如上所述,我们无法支持您的要求。(Sean Kim)

因此,他们显然知道这一点,但未尝试纠正此问题,因为他们要么不认为这是一个bug(我仍然坚信这是一个逻辑缺陷),要么他们没有时间/资源来纠正它。

底线 如果您的手机在屏幕关闭的情况下不发送加速度计事件,请尝试更新固件。如果仍然不能解决问题,而您真的想进行一些严重的黑客攻击,请重新实现硬件层-提示:可能与libsensors.so有关。


2
感谢马丁提供了非常完整的信息。我们真正需要的是一个列表,说明哪些手机支持屏幕外的加速度计事件,因为人们可能会在购买前需要此信息(例如我-我需要此信息)。也许是维基,人们可以测试他们的手机并更新列表。到处都有这样的清单吗?
Fletch 2012年

8
好吧,我列出了一个清单:saltwebsites.com/2012/android-accelerometers-screen-off
Fletch

2
惊人而全面的答案。会给一个以上的赞许:)在某种程度上,您可以通过侦听SCREEN_OFF和SCREEN_ON事件,获取新的唤醒锁并重新启动加速计服务来解决该问题。但同样,它仅适用于某些手机。
LambergaR 2012年

Subperb方式到ques和Ans
Shakeeb Ayaz 2014年

越狱能否删除此错误?
阿米尔

6

我不确定这是否真的可以为您提供帮助,但是我找到了解决方法(虽然不确定是否可以帮助节省电池)。

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

但是,在回声中0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness。屏幕关闭,并且输出是连续的。

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


!玩得好,没想到bash脚本。。我想稍后再试,即使我早已完成这项工作。。感谢您的输入!
马丁

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,该SDK使用设备传感器(加速度计/陀螺仪)数据并预测用户事件。我遇到了同样的问题。


2

我遇到了类似的问题,即使用其他系统服务的运行Android 4.0.2的三星Nexus会在屏幕关闭时停止/暂停(即使PARTIAL_WAKE_LOCK已获取a )。我的解决方案是使用SCREEN_DIM_WAKE_LOCKas作为:

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

完全关闭屏幕会更好,但是至少此解决方案有效,尽管如果我可以将a限制SCREEN_DIM_WAKE_LOCK为仅需要它们的设备/ OS会更好。


0

我不想让您失望,但是有些设备在进入睡眠模式时不会保持打开速度。有些会,有些则不会。您可以在商店中检查任何计步器减肥应用程序,其中大多数都明确指出这不适用于某些设备。


0

如果部分唤醒锁定选项不适用于您的电话,则意味着传感器的驱动程序已early_suspend启用。

有两种选择。

1:禁用EARLY_SUSPEND驱动程序

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

例如 cat / sys / module / earlysuspend / sensor 1/0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.