В более ранних статьях мы уже получали информацию об устройстве.
Теперь давайте копнем глубже и получим данные с доступных на устройстве сенсоров.
Их может быть много, а может и совсем чуть чуть, ранее мы уже смотрели на разные устройства, и в некоторых их было совсем не густо.
Полный их список можно получить здесь, пока их 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. )
Вот что получилось на выходе:
Показаний температуры у нас нет, т.к. и температурного сенсора на устройстве не нашлось (и метод 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 сам отсечет устройства, которые не имеют указанного сенсора.
Уведомление: Новости из мира Delphi 1.09 – 7.09 2014 |