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:
- ¿Dónde puedo encontrar recursos y muestras de código para hacer uso de la señal de un acelerómetro?
- Javascript 'deviceorientation' evento - ¿qué sensores se mide?
- ¿Cómo obtener orientación inicial para los cálculos con giroscopio?
- Problemas de tono en modo horizontal
- android sensortag azimut para la brújula no está funcionando (código java)
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.
- Desde la actualización de OTA a Marshmallow mi aplicación basada en giroscopio ya no funciona
- Configuración de sensibilidad personalizada en giroscopio a través de Android api, o el núcleo?
- ¿Hay alguna manera de recuperar datos de sensores múltiples en Android?
- Simulador de Sensor de Baja Energía Bluetooth
- Sensor de fusión implementado en Android?
- Accede a los sensores de Android a través de NDK
- Valor de retorno falso inesperado de android.hardware.SensorManager.registerListener en Android 4.3
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; }