当 Droid/Nexus One 屏幕关闭时,即使使用 WakeLock,加速计也会停止提供样本

发布于 2024-08-19 03:30:53 字数 889 浏览 10 评论 0原文

我有一些代码可以扩展服务并记录 Android 上的 onSensorChanged(SensorEvent event) 加速度计传感器读数。我希望即使在设备关闭时也能够记录这些传感器读数(我很注意电池寿命,并且在运行时这一点很明显)。当屏幕打开时,日志记录在 2.0.1 Motorola Droid 和 2.1 Nexus One 上运行良好。

但是,当手机进入睡眠状态(按下电源按钮)时,屏幕会关闭,并且 onSensorChanged 事件停止传递(通过每 N 次使用 Log.e 消息进行验证 onSensorChanged< /code> 被调用)。

服务获取wakeLock以确保其在后台保持运行;但是,似乎没有任何效果。我已经尝试了所有不同的 PowerManager。唤醒锁,但它们似乎都不重要。

_WakeLock = _PowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
_WakeLock.acquire();

关于屏幕关闭时是否能真正从传感器获取数据,存在相互矛盾的报道……有人在更现代版本的 Android (Eclair) 和硬件上有过这方面的经验吗?

这似乎表明它在 Cupcake 中起作用: http://groups.google.com/group/android-developers/msg/a616773b12c2d9e5

PS:在 G1 上,代码与 1.5 中的预期完全相同。当屏幕关闭、应用程序处于后台等时,日志记录会继续。

I have some code that extends a service and records onSensorChanged(SensorEvent event) accelerometer sensor readings on Android. I would like to be able to record these sensor readings even when the device is off (I'm careful with battery life and it's made obvious when it's running). While the screen is on the logging works fine on a 2.0.1 Motorola Droid and a 2.1 Nexus One.

However, when the phone goes to sleep (by pushing the power button) the screen turns off and the onSensorChanged events stop being delivered (verified by using a Log.e message every N times onSensorChanged gets called).

The service acquires a wakeLock to ensure that it keeps running in the background; but, it doesn't seem to have any effect. I've tried all the various PowerManager. wake locks but none of them seem to matter.

_WakeLock = _PowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
_WakeLock.acquire();

There have been conflicting reports about whether or not you can actually get data from the sensors while the screen is off... anyone have any experience with this on a more modern version of Android (Eclair) and hardware?

This seems to indicate that it was working in Cupcake:
http://groups.google.com/group/android-developers/msg/a616773b12c2d9e5

PS: The exact same code works as intended in 1.5 on a G1. The logging continues when the screen turns off, when the application is in the background, etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我的痛♀有谁懂 2024-08-26 03:30:53

我们推断这是从 2.0.1 开始的。这似乎是故意的,也许是被吹捧为一项功能的电池寿命提升的一部分。我们在 2.0 上进行了一次唤醒或解锁的工作,然后在更新时崩溃了,我们无法找到任何解决方法。 ;'( 如果保持 CPU 部分锁定并不重要,这应该始终阻止 CPU 休眠。从我通过 USB 记录调试的情况来看,似乎偶尔会提到传感器侦听器在休眠发生时发生变化。

用户发布了一个他声称适用于 motorola 设备的解决方法 - https://sites.google.com/a/bug-br.org.br/android/technical-documents

我测试了解决方法,从教程中得出以下代码和一些手动修改(有他的教程中提供的代码中存在一些“错误”):

public class ShakeWakeupService extends Service implements SensorEventListener{
     private Context mContext;
     SensorManager mSensorEventManager;
     Sensor mSensor;

     // BroadcastReceiver for handling ACTION_SCREEN_OFF.
     public BroadcastReceiver mReceiver = new BroadcastReceiver() {

         @Override
         public void onReceive(Context context, Intent intent) {
             // Check action just to be on the safe side.
             if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 Log.v("shake mediator screen off","trying re-registration");
                 // Unregisters the listener and registers it again.
                 mSensorEventManager.unregisterListener(ShakeWakeupService.this);
                 mSensorEventManager.registerListener(ShakeWakeupService.this, mSensor,
                     SensorManager.SENSOR_DELAY_NORMAL);
             }
         }
     };

         @Override
         public void onCreate() {
           super.onCreate();
           Log.v("shake service startup","registering for shake");
           mContext = getApplicationContext();
             // Obtain a reference to system-wide sensor event manager.
           mSensorEventManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
             // Get the default sensor for accel
           mSensor = mSensorEventManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
             // Register for events.
           mSensorEventManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);

             // Register our receiver for the ACTION_SCREEN_OFF action. This will make our receiver
             // code be called whenever the phone enters standby mode.
           IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
           registerReceiver(mReceiver, filter);
     }

     @Override
     public void onDestroy() {
        // Unregister our receiver.
         unregisterReceiver(mReceiver);
         // Unregister from SensorManager.
         mSensorEventManager.unregisterListener(this);
     }

     @Override
     public IBinder onBind(Intent intent) {
         // We don't need a IBinder interface.
  return null;
     }

 public void onShake() {
         //Poke a user activity to cause wake?
     }
     public void onAccuracyChanged(Sensor sensor, int accuracy) {
                //not used right now
            }
            //Used to decide if it is a shake
            public void onSensorChanged(SensorEvent event) {
                    if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) return;
                  Log.v("sensor","sensor change is verifying");
            }
      }

该解决方法对我有用,但在我运行 screebl 时不起作用,这是我的很多用户真正希望与我正在开发的功能结合使用的功能。

We've deduced this started as of 2.0.1. It seems to be intentional, perhaps part of the battery life boost that was touted as a feature. We had a working shake to wakeup or unlock on 2.0, then it broke on the update and we haven't been able to get any kind of workaround. ;'( It doesn't matter if CPU partial lock is held which is supposed to always prevent CPU from sleeping. From what I've seen logging debug over USB there appears to occasionally be mention of sensor listener changes as sleep happens.

A user posted a workaround that he claimed works on the motorola devices - https://sites.google.com/a/bug-br.org.br/android/technical-documents

I tested the workaround, coming up with the following code from the tutorial and some manual revision (there are a few "bugs" in his tutorial presented code):

public class ShakeWakeupService extends Service implements SensorEventListener{
     private Context mContext;
     SensorManager mSensorEventManager;
     Sensor mSensor;

     // BroadcastReceiver for handling ACTION_SCREEN_OFF.
     public BroadcastReceiver mReceiver = new BroadcastReceiver() {

         @Override
         public void onReceive(Context context, Intent intent) {
             // Check action just to be on the safe side.
             if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 Log.v("shake mediator screen off","trying re-registration");
                 // Unregisters the listener and registers it again.
                 mSensorEventManager.unregisterListener(ShakeWakeupService.this);
                 mSensorEventManager.registerListener(ShakeWakeupService.this, mSensor,
                     SensorManager.SENSOR_DELAY_NORMAL);
             }
         }
     };

         @Override
         public void onCreate() {
           super.onCreate();
           Log.v("shake service startup","registering for shake");
           mContext = getApplicationContext();
             // Obtain a reference to system-wide sensor event manager.
           mSensorEventManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
             // Get the default sensor for accel
           mSensor = mSensorEventManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
             // Register for events.
           mSensorEventManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);

             // Register our receiver for the ACTION_SCREEN_OFF action. This will make our receiver
             // code be called whenever the phone enters standby mode.
           IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
           registerReceiver(mReceiver, filter);
     }

     @Override
     public void onDestroy() {
        // Unregister our receiver.
         unregisterReceiver(mReceiver);
         // Unregister from SensorManager.
         mSensorEventManager.unregisterListener(this);
     }

     @Override
     public IBinder onBind(Intent intent) {
         // We don't need a IBinder interface.
  return null;
     }

 public void onShake() {
         //Poke a user activity to cause wake?
     }
     public void onAccuracyChanged(Sensor sensor, int accuracy) {
                //not used right now
            }
            //Used to decide if it is a shake
            public void onSensorChanged(SensorEvent event) {
                    if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) return;
                  Log.v("sensor","sensor change is verifying");
            }
      }

The workaround works for me, but will not work while I have screebl running, which is a feature a lot of my users really want working in conjunction with what I'm developing.

夜无邪 2024-08-26 03:30:53

刚刚用最近几天在互联网上流传的 FROYO FRF50 ROM 更新了我的 Nexus One,如果您有 PARTIAL_WAKELOCK,传感器现在似乎可以在屏幕关闭时再次工作。我不知道这是否会进入官方版本,尽管我的理解是这是基于一些 N1 用户收到的官方版本。因此,也许他们(再次)改变了主意,并在手机锁定时重新启用了传感器。手指交叉。

当然,他们可以在 2.2-r1 中再次禁用它们,谁知道呢……

Just updated my Nexus One with the FROYO FRF50 ROM that has been kicking around the internets for the last few days, and it seems that sensors now work again when the screen is off if you have a PARTIAL_WAKELOCK. I don't know if this will make it to the official build, although my understanding is that this is based on an official build that some N1 users received. So maybe they've changed their minds (once again), and re-enabled the sensors when the phone is locked. Fingers crossed.

Of course, they could just go and disable them again in 2.2-r1, who knows...

微凉徒眸意 2024-08-26 03:30:53

在 HTC EVO 上使用 SCREEN_DIM_WAKE_LOCK 对我来说很有效。

final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
_WakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
_WakeLock.acquire();

Using a SCREEN_DIM_WAKE_LOCK worked for me on the HTC EVO..

final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
_WakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
_WakeLock.acquire();
没有心的人 2024-08-26 03:30:53

看来这是一个 2.1 固件问题,我有必要解决这个问题,但我必须采取各种解决方法来覆盖所有版本。

我已经整理了一份可以工作/不工作/间歇性工作的手机和固件列表,以便我们可以测试手机或固件。

http://apprssd .com/2010/09/08/android-onsensorchanged-not-working-when-screen-lock-is-on/

如果您有可以更新列表的新手机,请告诉我。

It seems that it is a 2.1 firmware issue, it's necessary for me to get this fixed but i'm have to work in all sorts of workarounds to cover all versions.

I've been putting together a list of phones and firmwares which work / don't work / intermittently work so that we can either test the phone or firmware.

http://apprssd.com/2010/09/08/android-onsensorchanged-not-working-when-screen-lock-is-on/

If you have a new phone you can update the list with, let me know.

罪歌 2024-08-26 03:30:53

有一种替代解决方案(某种程度上),您可以使用以下方法保持屏幕始终打开:

Settings.System.putInt(getContentResolver(),
Settings.System.SCREEN_OFF_TIMEOUT, -1);

但这并不能阻止用户通过按下电源按钮强制屏幕关闭,然后传感器事件流停止。您还需要 WRITE_SETTINGS 权限才能正常工作。

上述重新注册传感器事件的解决方法在 Droid Eris 上不起作用,该系统运行 Android 2.1,预计永远不会升级。我已经使用了以下内容,但它似乎确实有效。这种方法不是取消注册并重新注册,而是在用户关闭屏幕时重新打开屏幕,尽管它会变暗。在下面的代码中,handler只是Activity中构造的一个简单的Handler(即Handler handler = new Handler();),mTurnBackOn是一个初始化为null的WakeLock。

public BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
            // Turn the screen back on again, from the main thread
            handler.post(new Runnable() {
            public void run() {
            if(mTurnBackOn != null)
                mTurnBackOn.release();

                mTurnBackOn = mPwrMgr.newWakeLock(
                    PowerManager.SCREEN_DIM_WAKE_LOCK |
                        PowerManager.ACQUIRE_CAUSES_WAKEUP,
                    "AccelOn");
                mTurnBackOn.acquire();
            }});
        }
    }
};

There's an alternate solution (sort of) where you keep the screen always turned on using:

Settings.System.putInt(getContentResolver(),
Settings.System.SCREEN_OFF_TIMEOUT, -1);

But this doesn't prevent the user from forcing the screen to off by pressing the power button and then the sensor event stream stops. You also need the WRITE_SETTINGS permission for this to work.

The workaround above of re-registering for sensor events does not work on the Droid Eris, which runs Android 2.1 and is not expected to ever get an upgrade. I've used the following though which does appear to work. Instead of un-registering and re-registering, this approach turns the screen back on when the user turns it off, although it comes back on dimmed. In the following code, handler is just a simple Handler constructed in the Activity (i.e., Handler handler = new Handler(); ) and mTurnBackOn is a WakeLock initialized to null.

public BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
            // Turn the screen back on again, from the main thread
            handler.post(new Runnable() {
            public void run() {
            if(mTurnBackOn != null)
                mTurnBackOn.release();

                mTurnBackOn = mPwrMgr.newWakeLock(
                    PowerManager.SCREEN_DIM_WAKE_LOCK |
                        PowerManager.ACQUIRE_CAUSES_WAKEUP,
                    "AccelOn");
                mTurnBackOn.acquire();
            }});
        }
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文