Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock

后端 未结 5 724
你的背包
你的背包 2020-12-05 00:50

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 sens

相关标签:
5条回答
  • 2020-12-05 01:03

    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.

    0 讨论(0)
  • 2020-12-05 01:11

    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();
    
    0 讨论(0)
  • 2020-12-05 01:15

    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...

    0 讨论(0)
  • 2020-12-05 01:16

    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.

    0 讨论(0)
  • 2020-12-05 01:19

    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();
                }});
            }
        }
    };
    
    0 讨论(0)
提交回复
热议问题