Подтвердить что ты не робот

SensorEventListener не получает незарегистрированный метод unregisterListener()

У меня очень простое приложение для Android: в действии у меня есть кнопка, и я запускаю/останавливаю OrientationListener. Однако, после его регистрации, в ddms я все еще вижу поток android.hardware.SensorManager $SensorThread] (Running).

Код регистрации:

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);
}

и отмена:

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

Метод unregisterListener() выполняется, однако он не очень сильно убивает нити датчиков, которые продолжают работать и разряжать батарею. Через несколько часов мое приложение отображается с 20-30% разрядом батареи. Как это возможно? Как я могу убедиться, что датчик незарегистрирован? Я не получаю никаких исключений и ошибок в logcat. Я попробовал запустить слушателя в Сервисе - то же самое.

4b9b3361

Ответ 1

Вы не показываете достаточно кода, чтобы точно сказать, но, возможно, ваш тест

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

просто неточно. То есть sensorManager или sensorEventListener может быть null, когда вы все еще зарегистрированы как прослушивание.

Ответ 2

Попробуйте установить диспетчер на нуль

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

а затем снова получите менеджера, когда вам это нужно. Это должно обеспечить непрерывность резьбы (это было в моем случае). Я не нашел никакой документации, объясняющей это поведение, но был бы заинтересован услышать об этом.

Ответ 3

У меня такая же проблема. Я проверил код Android. Соответствующий код находится в 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;
            }
        }
    }
}

и

        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");
        }
    }
}

Итак, похоже, что поток должен быть завершен, когда нет слушателей

Ответ 4

Я столкнулся с подобной проблемой.

Обходной путь для остановки датчика.

Я использовал статическое логическое mIsSensorUpdateEnabled. Установите значение "false", когда вы хотите прекратить получать значения от датчиков. И в методе onSensorChanged() проверьте значение логической переменной и снова сделайте вызов, чтобы отменить регистрацию датчиков. И на этот раз он работает. Датчики будут незарегистрированы, и вы больше не получите обратный вызов onSensorChanged.

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

Ответ 5

Может быть проблемой с областью. Попробуйте выполнить регистрацию значений датчикаEventListener и датчика при регистрации и отмене регистрации. (.toString()), чтобы убедиться, что они одинаковы.

Ответ 6

В моем случае, чтобы решить эту проблему, мне нужно было исправить контекст, который я использовал, чтобы получить SensorManager. Я был в Сервисе, и мне нужно было получить SensorManager таким образом:

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

Итак, просто удостоверьтесь, правильно ли вы получаете SensorManager.

Ответ 7

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

onСоздать вызов

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();
    }

Пожалуйста, позвоните в Destroy

if (sensorManager != null && mAccelerometer != null) 
{ 
    sensorManager.unregisterListener(sensorEventListener, mAccelerometer); sensorManager = null; 
}