티스토리 뷰

Mobile/Android

[Android] 센서 이해하기

춘햄 2022. 4. 30. 12:33

스마트폰이 가지고 있는 다양한 센서의 정보들은 SensorManager 라는 시스템 서비스를 통해 모두 같은 방식으로 사용할 수 있다. 

 

다음은 안드로이드에서 지원하는 대표적인 센서들이다. 

센서 이름 상수 설명
Accelerometer TYPE_ACCELEROMETER 가속도 감지, 외부의 충격량과 방향 감지
(단위: m/s^2)(중력 + 선형 가속)
Gyroscrope TYPE_GYROSCOPE 회전 정보 감지, 다양한 축을 따른 회전각 감지
Gravity TYPE_GRAVITY 축의 방향과 중력 감지
Light TYPE_LIGHT 빛의 세기 감지
Linear Acceleration TYPE_LINEAR_ACCELERATION 각 축에 따른 가속도를 감지하는 3차원 벡터
Proximity TYPE_PROXIMITY 근접한 물체와의 거리 감지(cm) 단말에 따라 가깝거나 먼 정도만 표시할 수도 있음
Temperature TYPE_TEMPERATURE 온도 감지
Orientation TYPE_ORIENTATION 방향각 감지(degree) 

스마트폰에서 가장 많이 사용되는 센서 중 하나인 가속 센서는 다양한 기준 축을 따라 기기가 얼마만큼의 속도로 움직이는지 측정할 수 있게 한다. 또 자이로스코프 센서는 가속 센서보다 더 많은 축을 기준으로 시간에 따라 회전하는 정보까지 확인할 수 있도록 해준다.

 

가속 센서의 경우, 중력 정보와 선형 가속 정보가 같이 계산되므로 가장 자주 사용하는 센서 중의 하나이다. 가속 센서를 이해하기 위해서는 가속 센서의 값을 계산할 줄 알아야 한다. 

 

단말을 테이블 위에 올려놓았을 경우 가속 센서의 값은 중력 가속도인 +9.81이 된다. 

 

방향의 경우에는 세 개의 값을 전달 받을 수 있는데, 첫 번째 값은 Azimuth라 하고 z축을 기준으로 북쪽 방향과 현재 감지되는 y축과의 차이를 나타낸다. 두번째 값은 pitch라 하고 x축을 기준으로 한 회전각을 나타낸다. 세번째 값은 Roll이라 하고 y축을 기준으로 한 회전각을 나타낸다. 

 

아래 그림을 보면서 이해하면 좀 더 쉽게 이해할 수 있다.


센서를 사용하기 위해 필요한 대표적인 클래스들은 다음과 같다. 

 

  • SensorManager: 센서를 다루기 위해 제공되는 시스템 서비스 객체.
  • Sensor: 각 센서의 정보를 포함하고 있는 객체
  • SensorEvent: 센서로부터 정보를 받을 때는 SensorEvent 객체로 전달되므로 이 객체를 처리하여 각 센서의 값을 바로바로 확인할 수 있다.

 

이제 예제를 한번 확인해보자.


◎activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              tools:context=".MainActivity" >

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

        <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="센서 리스트" />

        <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="첫번째 센서" />
    </LinearLayout>

    <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/holo_blue_bright">

        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

            <TextView
                    android:id="@+id/textView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="20sp" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

 

◎MainActivity.java

package com.example.samplesensor;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    TextView textView;

    SensorManager manager;
    List<Sensor> sensors;

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

        textView = findViewById(R.id.textView);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getSensorList();
            }
        });

        Button button2 = findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                registerFirstSensor();
            }
        });
    }

    // Sensor List 를 가져와서 화면에 출력
    public void getSensorList() {
        manager = (SensorManager) getSystemService(SENSOR_SERVICE);
        sensors = manager.getSensorList(Sensor.TYPE_ALL);

        int index = 0;
        for (Sensor sensor : sensors) {
            println("#" + index + " : " + sensor.getName());
            index++;
        }
    }

    //
    public void registerFirstSensor() {
        // Sensor Event 를 위한 리스너 설정
        manager.registerListener(
            new SensorEventListener() {
                @Override
                // 센서의 값이 변할 때마다 값을 화면에 출력
                public void onSensorChanged(SensorEvent event) {
                    String output = "Sensor Timestamp : " + event.timestamp + "\n\n";
                    for(int index = 0; index < event.values.length; ++index) {
                        output += ("Sensor Value #" + (index + 1) + " : " + event.values[index] + "\n");
                    }
                    println(output);
                }

                @Override
                // 센서의 정확도 변경 콜백
                public void onAccuracyChanged(Sensor sensor, int accuracy) {

                }
            },
            sensors.get(0),
            SensorManager.SENSOR_DELAY_UI);
    }

    public void println(String data) {
        textView.append(data + "\n");
    }
}

구현하기 그닥 어렵지는 않다. 첫번째 버튼을 누르면 모든 Type의 센서를 출력하고, 두번째 버튼을 눌렀을 때는 Sensor 리스트에 있는 센서의 값이 변경되었을 때 콜백 메서드를 호출하여 어떤 센서가 어떤 값으로 바뀌었는 지 확인할 수 있도록 한다.


Comments