Статьи

Android с нуля: аппаратные датчики

Одна из вещей, которая отличает разработку для мобильных устройств от других платформ, заключается в том, что мобильный телефон или планшет состоит из датчиков и другого оборудования, которое разработчики могут использовать для ввода данных. В этом уроке вы познакомитесь с сенсорной платформой Android. Вы узнаете, как определить, какие датчики доступны на устройстве и как считывать данные с этих датчиков.

Следует учитывать три основные категории базовых датчиков: движение, окружающая среда и положение устройства. Датчики движения обнаруживают изменения сил вокруг трех осей устройства: X, Y и Z, как показано здесь:

Оси X Y и Z мобильного устройства

Датчики движения включают гироскоп, акселерометр и датчики вектора вращения.

Датчики окружающей среды собирают информацию об окружающей среде, в которой находится телефон. Сюда входят датчики влажности и температуры окружающей среды, детектор света и барометры.

Последняя категория базовых датчиков, положение устройства, делает именно то, что вы ожидаете: она определяет положение устройства. В эту категорию входят датчики ориентации и магнитометр.

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

Теперь, когда вы немного узнали о типах датчиков в мобильных устройствах, пришло время начать считывать данные с реального оборудования. Давайте начнем с выяснения того, какие датчики доступны на устройстве.

Чтобы получить доступ к датчикам на устройстве, вам нужно будет использовать класс SensorManager , который вы можете получить как системный сервис из Activity .

1
mSensorManager = (SensorManager) getSystemService( Context.SENSOR_SERVICE );

Получив SensorManager , вы можете получить Sensor по умолчанию на основе типа или получить List объектов Sensor на основе параметра типа. В этом примере мы получим List всех объектов Sensor , например, так:

1
List<Sensor> sensorList = mSensorManager.getSensorList( Sensor.TYPE_ALL );

Вы заметите, что мы использовали TYPE_ALL здесь. Если нам нужно только определенное подмножество датчиков, мы можем передать любой из поддерживаемых атрибутов типа, таких как элементы в следующем, неисключительном списке.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
TYPE_AMBIENT_TEMPERATURE
TYPE_DEVICE_PRIVATE_BASE
TYPE_GAME_ROTATION_VECTOR
TYPE_GEOMAGNETIC_ROTATION_VECTOR
TYPE_GRAVITY
TYPE_GYROSCOPE
TYPE_GYROSCOPE_UNCALIBRATED
TYPE_HEART_BEAT
TYPE_HEART_RATE
TYPE_LIGHT
TYPE_LINEAR_ACCELERATION
TYPE_MAGNETIC_FIELD
TYPE_MAGNETIC_FIELD_UNCALIBRATED
TYPE_MOTION_DETECT

Если у вас есть Sensor с которыми вы хотите работать, вы можете начать извлекать из них данные.

Каждый объект Sensor содержит информацию о физическом оборудовании для этого датчика, например, мощность, задержка на входе, имя, тип и поставщик. Однако, если вы хотите получить информацию от этого датчика, вам нужно зарегистрировать SensorEventListener который будет вызываться через заданные интервалы с новыми показаниями информации.

1
mSensorManager.registerListener( this, mSensor, SensorManager.SENSOR_DELAY_UI );

Существует четыре скорости чтения: самая быстрая, игровая, обычная и пользовательский интерфейс. Некоторые позволят вам читать информацию чаще, но будут потреблять больше энергии от устройства. Чем реже опрашивается датчик, тем меньше энергии он будет использовать.

После регистрации onSensorChanged метод onSensorChanged слушателя будет вызываться с новым SensorEvent каждом SensorEvent датчика. SensorEvent оборачивает объект Sensor который предоставляет ему данные, а также информацию о времени, точности датчика и фактических входных данных.

Входные данные хранятся в массиве float с float называемых values . Длина values может варьироваться в зависимости от датчика. Например, акселерометр будет иметь три значения (вход X, Y и Z), тогда как барометр будет иметь только одно значение. Когда вы используете данные датчика, понимание того, какие данные доступны и как они хранятся в массиве values будет важно для понимания того, как вы создадите свое приложение, а также избежания сбоев из-за проблем, таких как ArrayIndexOutOfBoundsException .

1
2
3
4
5
6
7
8
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
    Log.e(«Tuts+», «Accuracy: » + sensorEvent.accuracy );
    Log.e(«Tuts+», «Timestamp: » + sensorEvent.timestamp);
    Log.e(«Tuts+», «Accelerometer X: » + sensorEvent.values[0]);
    Log.e(«Tuts+», «Accelerometer Y: » + sensorEvent.values[1]);
    Log.e(«Tuts+», «Accelerometer Z: » + sensorEvent.values[2]);
}

Приведенный выше фрагмент кода при запуске с акселерометром устройства выдаст следующий результат:

1
2
3
4
5
E/Tuts+: Accuracy: 3
E/Tuts+: Timestamp: 572565573007319
E/Tuts+: Accelerometer X: 0.80444336
E/Tuts+: Accelerometer Y: 1.7597351
E/Tuts+: Accelerometer Z: 9.425964

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

График, показывающий изменения по осям X Y и Z с течением времени

В то время как SensorEventListener будет продолжать предоставлять информацию с течением времени, TriggerEventListener будет прослушивать событие, а затем немедленно отключать себя. Этот тип слушателя используется для таких вещей, как значительное движение. Вы можете добавить TriggerEventListener в SensorManager следующим образом.

1
2
3
4
5
6
7
8
9
mSensorManager.requestTriggerSensor(new TriggerEventListener() {
    @Override
    public void onTrigger(TriggerEvent triggerEvent) {
        Log.e(«Tuts+», «onTrigger»);
        for(int i = 0; i < triggerEvent.values.length; i++ ) {
            Log.e(«Tuts+», «item » + i + «: » + triggerEvent.values[i]);
        }
    }
}, mSensor);

Если Sensor переданный в requestTriggerSensor является значимым датчиком движения, то вышеприведенное будет иметь выход при перемещении устройства следующим образом:

1
2
E/Tuts+: onTrigger
E/Tuts+: item 0: 1.0

Одна вещь, которую следует отметить как с SensorEventListener и с TriggerEventListener заключается в том, что они должны быть незарегистрированными в вашем SensorManager когда вы закончите их использовать, например, в onDestroy в ваших классах Fragment или Activity , чтобы предотвратить утечки в вашем приложении.

В этом уроке вы познакомились с сенсорной платформой Android. Вы узнали, как находить датчики на устройстве и получать от них информацию. Используя это, вы можете создавать сложные приложения, которые осведомлены об их среде, специальном вводе и действиях пользователей. Умение правильно использовать данные датчиков откроет много интересных функций и возможностей, которые вы можете использовать для своих приложений.