한 걸음 두 걸음

안드로이드 시스템 프로그래밍 #02 ] 모바일 센서의 종류 및 사용 방법 본문

FrontEnd/mobile system programming

안드로이드 시스템 프로그래밍 #02 ] 모바일 센서의 종류 및 사용 방법

언제나 변함없이 2019. 3. 13. 09:34
반응형

안드로이드가 지원하는 센서의 종류

  1. Motion sensor (가속력 및 회전력)
    : accelerometers, gravity sensors, gyroscopes, rotational vector sensors
  2. Environmental sensors (기온 기압 조도 습도 등)
    : barometers, photometers, thermometers
  3. Position Sensor
    : orientation sensors, magnetometers.

안드로이드 센서 사용을 위한 클래스 및 인터페이스 4가지

  1. SensorManager
  2. Sensor
  3. SensorEvent
  4. SensorEventListener

참고 develpoer documentation
https://developer.android.com/guide/topics/sensors?hl=ko

1. Sensormanager 클래스

안드로이드 센서를 관리하고 이용할 수 있도록 돕는 클래스로,
어떤 센서가 있고 그 센서가 제공하는 값의 범위가 어디에서 어디까지인지 알려준다.
가속도 센서와 같은 센서 값을 받아올려고할 때 값을 받아올 수 있게 한다.
(센서 이벤트 리스너 등록을 센서매니저를 통해 하게되면 센서값을 받아올 수 있게 된다.)

SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
여기서 SENSOR_SERVICE는 자기가 원하는 구체적인 센서로 설정해서 쓴다.
ex) LOCATION_SERVICE

참고 developer https://developer.android.com/reference/android/hardware/SensorManager.html?hl=ko

2. Sensor 클래스

센서매니저 클래스의 메소드를 활용하여 접근하고자 하는 센서의 객체를 선언할 수 있다.  
위에서 만들어놓은 sm.을 이용해  
Sensor accel = sm.getDefaultSensor(Sensor.TYPE\_ACCELEROMETER); //사용예시

Sensor에서 제공하는 클래스 메소드는 다음과 같다.

float getMaximumRange() 센서값의최대범위
int getMinDelay() 두개의센서이벤트사이의최소딜레이 (ms단위) 혹은0 (측정데이터에변화가 있을때만값을주는경우 )
String getName()
float getPower() 사용중에소모한파워(mA 단위)
String getStringType()
int getType()
String getVendor()
int getVersion()

보다 자세한 내용은 다큐먼트에서 확인,
https://developer.android.com/reference/android/hardware/Sensor.html?hl=ko

센서타입!
developer
https://developer.android.com/guide/topics/sensors/sensors_motion.html?hl=ko .

이는 sensor 클래스에 정의된 상수이므로 가져다가 쓰면 된다.

실제로 내 안드로이드 폰에 내장된 센서가 제공하는 정보를 확인해보자.
TextView text 하나 있음.

package kr.ac.koreatech.swkang.msp01_sensorlist;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;

import java.util.List;

public class MainActivity extends AppCompatActivity {

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

        String list = "";
        // SensorManager 객체를 getSystemService 메소드를 통해 얻음
        SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        // 모든 타입의 센서 목록을 얻음
        List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_ALL);

        list += "전체 센서 수: " + sensors.size() + "\n";
        int i = 0;
        for(Sensor s: sensors) {
            list += "" + i++ + " name: " + s.getName() + "\n" + "power: " + s.getPower() + "\n"
                    + "resolution: " + s.getResolution() + "\n" + "range: " + s.getMaximumRange() + "\n"
                    + "vendor: " + s.getVendor() + "\n" + "min delay: " + s.getMinDelay() + "\n\n";
        }

        TextView text = (TextView)findViewById(R.id.text);
        // TextView에 텍스트 내용이 화면 크기를 넘어서 들어갈 때 스크롤 가능하게 만들기 위한 메소드 호출
        text.setMovementMethod(new ScrollingMovementMethod());
        text.setText(list);
    }
}

결과화면

3. SensorEventListener 인터페이스

센서 값이 변경되었을 때 SensorManager한테 이벤트형태로 값을 전달받을 수 있도록 해줍니다.
등록방법 ) SensorManager에 있는 registerListener메소드를 활용하여 등록합니다.
boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs)

  • listener: SensorEventListener객체
    •sensor: 데이터를받고싶은센서객체

  • samplingPeriodUs는얼마나 자주 변경된 데이터를 받을지 값을 설정하는 것인데

SENSOR_DELAY_NORMAL
SENSOR_DELAY_UI
SENSOR_DELAY_GAME
SENSOR_DELAY_FASTEST

4가지 상수로 SensorManager에 정의되어있다. 이는 밑으로 내려갈수록 빠르며, 기기마다 조금씩 차이날 수 있다.

구현
SensorEventListener 인터페이스를 구현하기 위해서는 두개의 메소드를 구현해야함
public void onAccuracyChanged(Sensor sensor, intaccuracy)
등록된 센서의 정확도가 변경됐을때 호출
public void onSensorChanged(SensorEventevent)
센서값이 변했을 때 호출.

사용예시

 public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
            mText.setText("방향 센서값\n\n방위각: " + event.values[0]
                    + "\n피치: " + event.values[1] + "\n롤: " + event.values[2]);
        }
    }

SensorEvent객체로데이터를전달받게됨

해제
센서 데이터 업데이트가 필요하지 않으면 반드시 이를 해제시켜주어야한다.
public void unregisterListener(SensorEventListenerlistener, Sensor sensor) public void unregisterListener(SensorEventListenerlistener)

등록 및 해제 예시

  @Override
    protected void onResume() {
        super.onResume();
        // SensorEventListener 등록
        mSensorManger.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_UI);
    }//this인 이유는 implements로 SensorEventListener 해놓았기때문~

    @Override
    protected void onPause() {
        super.onPause();
        // SensorEventListener 해제
        mSensorManger.unregisterListener(this);
    }

참고 https://developer.android.com/reference/android/hardware/SensorEventListener.html?hl=ko

아 내 사랑 보고싶다.ㅎㅎ

4. SensorEvent 클래스

Sensor객체 내에는 센서에 대한 정보(센서타입, 시간, 데이터 등)을 담고 있으므로 이를 뽑아서 사용하면 된다.

public intaccuracy 이 이벤트의 정확도
public Sensor sensor 이 이벤트를 발생한 센서
public long timestamp 이벤트가 발생한 시각
public final float[] values 센서 데이터를 담고 있는 배열.
센서 타입에따라 길이나 그 내용은 달라짐->예)
조도센서일경우 int 값 하나라서 values[0]만 쓰이겠지만
ex) Sensor.TYPE_LIGHT -> values[0]
가속도나 자이로센서 등은 값이 3개씩(x, y, z) 들어가있어서 values[0][1][2]값을 쓴다.
ex) Sensor.TYPE_ORIENTATION ->

values[0]: 방위각(Azimuth) 북쪽과y축사이각도(0 to 359). z축중심회전각0=North, 90=East, 180=South, 270=West
•values[1]: 피치(Pitch) x축중심회전각(-180 to 180)
•values[2]: 롤(Roll) y축중심회전각(-90 to 90).

실습코드, android xml엔 TextView text 하나 있음~

package kr.ac.koreatech.swkang.msp02_orientationsensor;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {
    private SensorManager mSensorManger;
    private Sensor mOrientation;
    TextView mText;

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

        mSensorManger = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        mOrientation = mSensorManger.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        mText = (TextView)findViewById(R.id.text);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // SensorEventListener 등록
        mSensorManger.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_UI);
    }//this인 이유는 implements로 SensorEventListener 해놓았기때문~

    @Override
    protected void onPause() {
        super.onPause();
        // SensorEventListener 해제
        mSensorManger.unregisterListener(this);
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
            mText.setText("방향 센서값\n\n방위각: " + event.values[0]
                    + "\n피치: " + event.values[1] + "\n롤: " + event.values[2]);
        }
    }
}

실습과제

중력과 가속도 센서값(x,y,z) 받아와서 출력하기
결과화면

package kr.ac.koreatech.swkang.msp02_orientationsensor;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {
    private SensorManager mSensorManger;
    private Sensor mOrientation;
    private Sensor linearSensor;
    TextView mText;
    TextView linearText;

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

        mSensorManger = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        mOrientation = mSensorManger.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        linearSensor = mSensorManger.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
        mText = (TextView)findViewById(R.id.text);
        linearText = (TextView)findViewById(R.id.linearTextView);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // SensorEventListener 등록
        mSensorManger.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_UI);
        mSensorManger.registerListener(this, linearSensor, SensorManager.SENSOR_DELAY_UI);
    }//this인 이유는 implements로 SensorEventListener 해놓았기때문~

    @Override
    protected void onPause() {
        super.onPause();
        // SensorEventListener 해제
        mSensorManger.unregisterListener(this);
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            mText.setText("중력 센서값\n\nx : " + event.values[0]
                    + "\ny: " + event.values[1] + "\nz: " + event.values[2]);
        }else if(event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION){
            linearText.setText("가속도 센서값\n\nx: " + event.values[0]
                    + "\ny: " + event.values[1] + "\nz: " + event.values[2]);
        }
    }
}

반응형