Собираем показания датчиков с Android смартфона

В своем первом посте на Хабре я бы хотел рассказать о том, как получать данные датчиков в ОС Android, а конкретно — угол наклона вашего аппарата во всех трех плоскостях. Заинтересовавшихся прошу под кат.


Датчики ОС Android делятся на три категории: движения, положения и окружающей среды. Датчики эти могут быть самыми разными:
  • Акселерометр
  • Гироскоп
  • Датчик освещения
  • Датчик магнитных полей
  • Акселерометр
  • Барометр
  • Датчик поднесения телефона к голове
  • Датчик температуры аппарата
  • Датчик температуры окр. среды
  • Измеритель относительной влажности
  • И т.д.


Естественно, их набор зависит от «комплектации» аппарата, но есть и датчики, присутствующие в большинстве смартфонов на Android — акселерометр и гироскоп.

Посредством этих датчиков мы можем узнать положение телефона в пространстве, а именно углы наклона аппарата во всех трех плоскостях (XY, YZ, ZX). Этим мы и займемся!

Для начала создадим новый проект и накидаем простенькое отображение с тремя надписями для вывода показаний датчиков и соответствующими подписями к ним. У меня получилось что-то вроде этого:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="Угол XY" />

        <TextView
            android:id="@+id/xyValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="0" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/textView3"
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="Угол XZ" /> />

        <TextView
            android:id="@+id/xzValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="0" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearLayout3"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/textView5"
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="Угол ZY" />

        <TextView
            android:id="@+id/zyValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="25dp"
            android:text="0" />

    </LinearLayout>

</LinearLayout>


В главной активити объявление класса приведем к виду:

public class Main extends Activity implements SensorEventListener {


Класс SensorEventListener поможет нам отследить события на датчиках.

У вас должно появиться четыре обязательных метода:

@Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) { //Изменение точности показаний датчика
  }

@Override
  protected void onResume() {
  }

@Override
  protected void onPause() {
  }

@Override
  public void onSensorChanged(SensorEvent event) { //Изменение показаний датчиков
  }


Как вы уже наверное догадались, нас вскоре заинтересует последний метод. А пока объявим необходимые нам переменные:

  private SensorManager mSensorManager; 
  private Sensor mOrientation;

  private float xy_angle;
  private float xz_angle;
  private float zy_angle;

  private TextView xyView;
  private TextView xzView;
  private TextView zyView;


Первая переменная — менеджер сенсоров устройства. Именно она даст нам доступ к интересующему нас датчику. Для этого событие onCreate сделаем похожим на это:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // Получаем менеджер сенсоров
    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); // Получаем датчик положения
    
    xyView = (TextView) findViewById(R.id.xyValue);  //
    xzView = (TextView) findViewById(R.id.xzValue);  // Наши текстовые поля для вывода показаний
    zyView = (TextView) findViewById(R.id.zyValue);  //
  }


Ну вот, почти закончили! Осталось только получить значения и вывести в текстовые поля. Вспомним про событие onSensorChanged. Если помните в него передается параметр SensorEvent event. Он-то и содержит значения углов наклона в градусах. Поэтому делаем финальный штрих и приводим событие к виду:

public void onSensorChanged(SensorEvent event) {
    xy_angle = event.values[0]; //Плоскость XY
    xz_angle = event.values[1]; //Плоскость XZ
    zy_angle = event.values[2]; //Плоскость ZY
    
    xyView.setText(String.valueOf(xy_angle));
    xzView.setText(String.valueOf(xz_angle));
    zyView.setText(String.valueOf(zy_angle));
}


Все готово! Думаю, понятно, что виртуальный смартфон вы повертеть не сможете. Поэтому для тестирования вам понадобится реальный аппарат. Запускаем, вертим наш смартфон и следим за цифрами.

Если кому-то понадобится, то выкладываю apk сделаный по примеру.

Надеюсь, пост оказался полезным и понятным для вас!

UPD: Как оказалось, можно протестировать и в эмуляторе. Спасибо BlackStream за ссылку!
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 18

    0
    Когда-то была одна идейка и тоже делал подобное приложение для тестирования датчиков.

    В статье не хватает ссылки на документацию по SensorManager, где и находится практически весь исходный код примера.
      +3
      Точно, хотел в конце дать ссылку, но радость от первой написанной статьи на Хабре… ну, Вы понимаете :)
        +2
        Повертеть и потестировать можно и в эмуляторе.
        code.google.com/p/openintents/wiki/SensorSimulator

          0
          Спасибо, не знал, исправил)
          +2
          Как не стыдно выкладывать старую хрень?

          public static final int SENSOR_ORIENTATION

          Since: API Level 1
          This constant is deprecated.

          Сенсор Orientation депрекэйтед уже несколько лет!!!

          читайте первоисточники — developer.android.com/reference/android/hardware/SensorManager.html#getOrientation(float[], float[])

            0
            Да тут вообще вся статья — тупо перевод документации. Ни грамма полезной или новой информации в статье.
              0
              Не думаю, что почти 30 человек добавили в избранное бесполезную статью…
                0
                И теперь 30 человек будут использовать deprecated метод.
                  0
                  Что говорит об их уровне :) И инстинкте собирательства.

                  Хотите сделать полезную статью: перевидите для этих 30 — android-developers.blogspot.com/2010/09/one-screen-turn-deserves-another.html

                  она объясняеть ПОЧЕМУ sensor orientation is deprecated
                0
                я прошу прощения, но в коде в упор не вижу использования SENSOR_ORIENTATION
                  0
                  Sensor.TYPE_ORIENTATION
                0
                пример ПРАВИЛЬНОГО использования ориентации — stackoverflow.com/questions/7046608/getrotationmatrix-and-getorientation-tutorial
                  +1
                  Акселерометр два раза для надежности в список включили? :)
                    0
                    Вероятно опечатался)
                    0
                    Недавно натолкнулся на похожее приложение:
                    market.android.com/details?id=com.fivasim.androsensor

                    Кстати, а чего на маркете не опубликовали?
                      0
                      Оно ведь само по себе не несет никакой практической пользы, исключительно в образовательных целях.
                      0
                        0
                        В топике по ссылке ничего не объясняется. Просто приведен исходный код программы.

                      Only users with full accounts can post comments. Log in, please.