Получение информации с сенсоров устройства Android

В более ранних статьях мы уже получали информацию об устройстве.

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

Их может быть много, а может и совсем чуть чуть, ранее мы уже смотрели на разные устройства, и в некоторых их было совсем не густо.

Полный их список можно получить здесь, пока их 13.

Для получения информации с сенсоров мы будем использовать класс SensorManager.

Его мы уже использовали в классе Tools для получения полного списка устройств.

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

Для этого у класса нашей активности объявим интерфейс SensorEventListener и теперь при работе с SensorManager в места где нужен экземпляр слушателя, достаточно написать this.

[cce lang=»java» tab_size=»2″ no_links=»false»]

public class MainActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;

……..

[/cce]

Теперь Eclipse должен заругаться:

Multiple markers at this line
— The type MainActivity must implement the inherited abstract method
SensorEventListener.onAccuracyChanged(Sensor, int)
— The type MainActivity must implement the inherited abstract method
SensorEventListener.onSensorChanged(SensorEvent)

В переводе на русский нужно реализовать два абстрактных метода onSensorChanged и onAccuracyChanged.

Первый произойдет, когда показания сенсора изменились, а второй — когда изменилась точность замеров сенсора.

Мы будем использовать только первый, в нём будем обновлять данные на экране устройства.

Вот код обновленной разметки activity_main.xml:

[cce lang=»xml» tab_size=»2″ no_links=»false»]

<RelativeLayout xmlns:android=»http://schemas.android.com/apk/res/android»
xmlns:tools=»http://schemas.android.com/tools»
android:layout_width=»match_parent»
android:layout_height=»match_parent» >

<TextView
android:id=»@+id/tv_info»
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:layout_alignParentLeft=»true»
android:text=»@string/hello_world» />

<TextView
android:id=»@+id/tv1″
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:layout_below=»@+id/tv_info»
android:layout_marginTop=»20dp»
android:text=»@string/hello_world» />

<TextView
android:id=»@+id/tv2″
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:layout_alignParentLeft=»true»
android:layout_below=»@+id/tv1″
android:layout_marginTop=»20dp»
android:text=»@string/hello_world» />

<TextView
android:id=»@+id/tv3″
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:layout_alignParentLeft=»true»
android:layout_below=»@+id/tv2″
android:layout_marginTop=»20dp»
android:text=»@string/hello_world» />

<TextView
android:id=»@+id/tv_sensors»
android:layout_width=»wrap_content»
android:layout_height=»wrap_content»
android:layout_alignParentLeft=»true»
android:layout_below=»@+id/tv3″
android:layout_marginTop=»20dp»
android:text=»@string/hello_world» />

</RelativeLayout>

[/cce]

Данные с сенсоров будем выводить в TextView — tv_sensors.

В методе активности onResume() регистрируем слушателя:

[cce lang=»java» tab_size=»2″ no_links=»false»]

mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_UI);

[/cce]

А в методе onPause() слушателя аннулируем:

[cce lang=»java» tab_size=»2″ no_links=»false»]

mSensorManager.unregisterListener(this);

[/cce]

У mSensorManager.registerListener три параметра: слушатель(SensorEventListener object), сенсор и период его обновления.

Сенсор получаем через константу, к примеру тут у нас сенсор освещённости

[cce lang=»java» tab_size=»2″ no_links=»false»]

mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)

[/cce]

Период обновления задаем тоже через константу:

[cce lang=»java» tab_size=»2″ no_links=»false»]

SensorManager.SENSOR_DELAY_UI

[/cce]

Пока их придумали 4:

  • SENSOR_DELAY_FASTEST_UI
  • SENSOR_DELAY_GAME
  • SENSOR_DELAY_NORMAL
  • SENSOR_DELAY_UI

Нужно отметить, что работает этот период на каждом устройстве по-разному.

Вот код получившего в итоге класса активности:

[cce lang=»java» tab_size=»2″ no_links=»false»]

package com.rusdelphi.tools;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
StringBuilder mInfo = new StringBuilder();
StringBuilder mLight = new StringBuilder(«Освещенность:»);
StringBuilder mTemperature = new StringBuilder(«Температура:»);
StringBuilder mPressure = new StringBuilder(«Давление:»);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

}

@Override
protected void onStart() {
super.onStart();
TextView tv_info = (TextView) findViewById(R.id.tv_info);
String info = «Доступ к интернет:»
+ (Tools.isOnline(this) ? «есть» : «нет») + «\n»;

info += «Модель:» + Build.MODEL + «\n»;
info += «Производитель:» + Build.MANUFACTURER + «\n»;
info += «Версия ПО: » + Build.VERSION.RELEASE + «\n»;
info += «Версия SDK: » + Build.VERSION.SDK_INT + «\n»;
tv_info.setText(info);

TextView tv1 = (TextView) findViewById(R.id.tv1);
tv1.setText(«Уровень заряда батареи » + Tools.getBatteryLevel(this));
TextView tv2 = (TextView) findViewById(R.id.tv2);
tv2.setText(«Температура батареи » + Tools.getBatteryTemperatute(this));
TextView tv3 = (TextView) findViewById(R.id.tv3);
tv3.setText(«Список доступных сенсоров на устройстве »
+ Tools.getSensorsList(this).toString());
}

@Override
protected void onResume() {
mSensorManager = (SensorManager) this
.getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, mSensorManager
.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE),
SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
SensorManager.SENSOR_DELAY_UI);
super.onResume();
}

@Override
protected void onPause() {
mSensorManager.unregisterListener(this);
super.onPause();
}

@Override
public void onSensorChanged(SensorEvent event) {
mInfo = new StringBuilder();
if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
mLight = new StringBuilder(«Освещенность:»);
mLight.append(event.values[0]);
}
if (event.sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE) {
mTemperature = new StringBuilder(«Температура:»);
mTemperature.append(event.values[0]);
}
if (event.sensor.getType() == Sensor.TYPE_PRESSURE) {
mPressure = new StringBuilder(«Давление:»);
mPressure.append(event.values[0]);
}
mInfo.append(String.format(«%1$s\n», mLight));
mInfo.append(String.format(«%1$s\n», mTemperature));
mInfo.append(String.format(«%1$s\n», mPressure));

TextView tv_sensors = (TextView) findViewById(R.id.tv_sensors);

tv_sensors.setText(mInfo.toString());
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
}
[/cce]

Использовано всего три простых датчика: освещенности, температуры и давления.

Их показания приходят в переменной event.values[0], если использовать более сложные датчики, то значений будет больше

К примеру вот датчик положения устройства, у него данные (values) приходят тремя параметрами.

В методе onSensorChanged мы не используем класс String, потому как при конкатенации строк он значительно медленнее работает, чем StringBuilder .

Переход на новую строку в нём реализован через String.format:

[cce lang=»java» tab_size=»2″ no_links=»false»]

String.format(«%1$s\n», light)

[/cce]

Сенсоры и устройства всё время развиваются и сегодня Eclipse  радостно сообщил, что : The field Sensor.TYPE_TEMPERATURE is deprecated. Поискав в доках, нашел, что он устарел с 20 API  (This constant was deprecated in API level 20. use  Sensor.TYPE_AMBIENT_TEMPERATURE instead. )

Вот что получилось на выходе:

device-2014-09-04-150035Показаний температуры у нас нет, т.к. и температурного сенсора на устройстве не нашлось (и метод getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE) вернул null).

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

Вот к примеру шагомер:

[cce lang=»xml» tab_size=»2″ no_links=»false»]

<uses-feature android:name=»android.hardware.sensor.stepcounter» android:required=»true» />

[/cce]

С такой записью в манифесте  Google Play сам отсечет устройства, которые не имеют указанного сенсора.

Нашли ошибку в тексте?

Получение информации с сенсоров устройства Android: 1 комментарий

  1. Уведомление: Новости из мира Delphi 1.09 – 7.09 2014 |

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *