25

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

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

该服务获取一个wakeLock 以确保它在后台继续运行;但是,它似乎没有任何效果。我已经尝试了所有各种 PowerManager。唤醒锁,但它们似乎都不重要。

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

关于您是否可以在屏幕关闭时实际从传感器获取数据的报道相互矛盾......有人在更现代的Android(Eclair)和硬件版本上对此有任何经验吗?

这似乎表明它在纸杯蛋糕中工作: http ://groups.google.com/group/android-developers/msg/a616773b12c2d9e5

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

4

5 回答 5

10

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

一位用户发布了一个他声称适用于摩托罗拉设备的解决方法 - 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 时不起作用,这是我的很多用户真正希望与我正在开发的功能一起使用的功能。

于 2010-01-30T08:44:15.457 回答
1

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

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

于 2010-05-23T22:12:26.313 回答
1

在 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();
于 2011-11-16T20:27:19.083 回答
0

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

我一直在整理手机和固件的列表,这些手机和固件可以工作/不工作/间歇性工作,以便我们可以测试手机或固件。

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

如果你有一部新手机,你可以更新列表,请告诉我。

于 2010-09-10T06:10:45.210 回答
0

有一个替代解决方案(某种),您可以使用以下方式始终打开屏幕:

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

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

上述重新注册传感器事件的解决方法不适用于运行 Android 2.1 且预计不会升级的 Droid Eris。我已经使用了以下内容,但它似乎确实有效。这种方法不是取消注册和重新注册,而是在用户关闭屏幕时重新打开屏幕,尽管它会重新变暗。在下面的代码中,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();
            }});
        }
    }
};
于 2010-10-24T19:19:28.763 回答