В более ранних статьях мы уже получали информацию об устройстве.
Теперь давайте копнем глубже и получим данные с доступных на устройстве сенсоров.
Их может быть много, а может и совсем чуть чуть, ранее мы уже смотрели на разные устройства, и в некоторых их было совсем не густо.
Полный их список можно получить здесь, пока их 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 |