SensorEventListener no obtiene unregistered con el método unregisterListener ()

Tengo aplicación Android muy simple: en la actividad tengo un botón y comienzo / detener el OrientationListener. Sin embargo, después de anular el registro, en ddms todavía puedo ver el hilo android.hardware.SensorManager $ SensorThread] (en ejecución) .

El código de registro:

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ORIENTATION); if (sensors.size() > 0) { sensor = sensors.get(0); running = sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_FASTEST); } 

Y desregistro:

 try { if (sensorManager != null && sensorEventListener != null) { sensorManager.unregisterListener(sensorEventListener,sensor); running = false; } } catch (Exception e) { Log.w(TAG, e.getMessage()); } 

El método unregisterListener() se ejecuta, sin embargo, no mata el hilo de los sensores con mucha frecuencia, lo que sigue funcionando y drenando la batería. Después de algunas horas mi aplicación se enumera con 20-30% de drenaje de la batería. ¿Cómo es eso posible? ¿Cómo puedo asegurarme de que el sensor no esté registrado? No recibo ninguna excepción ni ningún error en el logcat. Traté de ejecutar al oyente en el servicio – lo mismo.

Estoy teniendo el mismo problema. Comprobé el código de Android. El código correspondiente está en SensorManager.java

 private void unregisterListener(Object listener) { if (listener == null) { return; } synchronized (sListeners) { final int size = sListeners.size(); for (int i=0 ; i<size ; i++) { ListenerDelegate l = sListeners.get(i); if (l.getListener() == listener) { sListeners.remove(i); // disable all sensors for this listener for (Sensor sensor : l.getSensors()) { disableSensorLocked(sensor); } break; } } } } 

y

  public void run() { //Log.d(TAG, "entering main sensor thread"); final float[] values = new float[3]; final int[] status = new int[1]; final long timestamp[] = new long[1]; Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); if (!open()) { return; } synchronized (this) { // we've open the driver, we're ready to open the sensors mSensorsReady = true; this.notify(); } while (true) { // wait for an event final int sensor = sensors_data_poll(sQueue, values, status, timestamp); int accuracy = status[0]; synchronized (sListeners) { if (sensor == -1 || sListeners.isEmpty()) { // we lost the connection to the event stream. this happens // when the last listener is removed or if there is an error if (sensor == -1 && !sListeners.isEmpty()) { // log a warning in case of abnormal termination Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor); } // we have no more listeners or polling failed, terminate the thread sensors_destroy_queue(sQueue); sQueue = 0; mThread = null; break; } final Sensor sensorObject = sHandleToSensor.get(sensor); if (sensorObject != null) { // report the sensor event to all listeners that // care about it. final int size = sListeners.size(); for (int i=0 ; i<size ; i++) { ListenerDelegate listener = sListeners.get(i); if (listener.hasSensor(sensorObject)) { // this is asynchronous (okay to call // with sListeners lock held). listener.onSensorChangedLocked(sensorObject, values, timestamp, accuracy); } } } } } //Log.d(TAG, "exiting main sensor thread"); } } } 

Así que parece que el hilo debe ser terminado cuando ya no hay oyentes

Usted no muestra el código suficiente para decir con seguridad, pero tal vez su prueba

 if (sensorManager != null && sensorEventListener != null) 

Simplemente no es exacta. Es decir, sensorManager o sensorEventListener puede ser null cuando todavía está registrado como escuchando.

Intenta establecer el gestor en null

 sensorManager.unregisterListener(sensorEventListener,sensor); sensorManager = null; 

Y luego obtener el gerente de nuevo cuando lo necesite. Esto debería hacer que el hilo termine de forma consistente (lo hizo en mi caso). No he encontrado ninguna documentación explicando este comportamiento, pero estaría interesado en saberlo.

Me enfrenté a un problema similar.

Solución para detener el sensor.

Utilicé un boolean estático mIsSensorUpdateEnabled . Póngalo en 'false' cuando desee dejar de obtener los valores de los sensores. Y en el método onSensorChanged (), compruebe el valor de la variable booleana y vuelva a hacer para llamar para anular el registro de los sensores. Y esta vez, funciona. Los sensores estarían sin registrar y ya no se obtendrá onSensorChanged callback.

 public class MainActivity extends Activity implements SensorEventListener { private static boolean mIsSensorUpdateEnabled = false; private SensorManager mSensorManager; private Sensor mAccelerometer; @override protected void onCreate(){ mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); } private startSensors(){ mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); int delay = 100000; //in microseconds equivalent to 0.1 sec mSensorManager.registerListener(this, mAccelerometer, delay ); mIsSensorUpdateEnabled =true; } private stopSensors(){ mSensorManager.unregisterListener(this, mAccelerometer); mIsSensorUpdateEnabled =false; } @Override public void onSensorChanged(SensorEvent event) { if (!mIsSensorUpdateEnabled) { stopSensors(); Log.e("SensorMM", "SensorUpdate disabled. returning"); return; } //Do other work with sensor data } } 

Podría ser un problema con el alcance. Intente registrar los valores de sensorEventListener y sensor cuando se registre y anule su registro. (.toString ()) para asegurarse de que son iguales.

En mi caso, para resolver este problema necesitaba corregir el contexto que estaba utilizando para obtener SensorManager. Yo estaba dentro de un Servicio, y necesitaba obtener el SensorManager de esta manera:

 SensorManager sensorManager = (SensorManager) getApplicationContext().getSystemService(SENSOR_SERVICE); 

Por lo tanto, sólo certificar si usted está recibiendo el SensorManager de la manera correcta.

 //Declaration of SensorManager private SensorManager sensorManager; private Sensor mAccelerometer; private SensorEventListener sensorEventListener; 

OnCreate llamada a

 try { sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE); sensorManager.registerListener(sensorEventListener=new SensorEventListener() { int orientation = -1; @Override public void onSensorChanged(SensorEvent event) { if (event.values[1] < 6.5 && event.values[1] > -6.5) { if (orientation != 1) { Log.d("Sensor", "Landscape"); } orientation = 1; } else { if (orientation != 0) { Log.d("Sensor", "Portrait"); } orientation = 0; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }, mAccelerometer=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME); } catch (Exception e) { e.printStackTrace(); } 

Por favor, llame a Destroy

 if (sensorManager != null && mAccelerometer != null) { sensorManager.unregisterListener(sensorEventListener, mAccelerometer); sensorManager = null; } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.