首页 文章

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

提问于
浏览
64

我正在为计算机科学的最终论文开发一个应用程序,我需要收集并记录加速度计数据 . 我需要一整天才能获得它,因此存在严重的电池限制(例如,我无法启动屏幕) . 此外,这不是一个以市场为目标的应用程序,因此如果需要,做一些严重的黑客攻击,甚至低级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)

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

  • 还有其他解决方法或黑客攻击吗?

如果问题在固件3.0及更高版本中持续存在,那么拥有更新电话的任何人都可以测试一下吗?

[UPDATE]

Unfortunately, it seems to be a bug with some cellphones. More details in my answer.

6 回答

  • 2

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

    我需要提供恒定的加速度计数据,并且不能让加密狗为我测量这些数据 - 我有一个带蓝牙和加速度计的Arduino,所以我可以实现这个解决方案 . 所以我决定手机的临时解决方案是让屏幕亮(变暗)并忽略电池消耗 . 稍后我会使用另一个安卓手机进行电池使用测试,该手机可以关闭屏幕 .

    More information about the bug

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

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

    E-mails exchanged with HR department of LG

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

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

    对于我收到的回复:

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

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

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

    然后我收到了这个答案:

    据我所知,Dev . 团队,那不是bug . 由于H / W架构,这款手机无限 . 我们需要重新设计HAL架构和设备驱动程序以支持您的请求 . 但是,正如您所知,由于缺乏资源,这太难了 . 我们正努力帮助您完成所有工作,但我们无法像我提到的那样支持您的请求 . (肖恩金)

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

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

  • 63

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

    使用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版本 .

  • 6

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

  • 0

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

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

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

  • 2

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

  • 0

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

    有两种选择 .

    1:在驱动程序中禁用 EARLY_SUSPEND

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

    恩 . cat / sys / module / earlysuspend / sensor 1/0

    IMO第二种选择应该从一开始就存在 .

相关问题