프로젝트명 | TiltSensor |
기능 |
|
핵심 구성요소 |
|
|
스텝1 액티비티의 생명주기 알아보기
액티비티 생명주기 출처 : https://developer.android.com/guide/components/activities/activity-lifecycle
스텝2 센서 사용하기
센서 목록
Sensor 클래스에 정의된 센서 목록
센서 | 설명 | 용도 |
TYPE_ACCELEROMETER | 가속도 센서 | 동작 감지(흔들림, 기울임 등) |
TYPE_AMBIENT_TEMPERATURE | 주변 온도 센서 | 대기 온도 모니터링 |
TYPE_GRAVITY | 중력 센서 | 동작 감지( 흔들림, 기울임 등) |
TYPE_GYROSCOPE | 자이로 센서 | 회전 감지 |
TYPE_LIGHT | 조도 센서 | 화면 밝기 제어 |
TYPE_LINEAR_ACCELERATION | 선형 가속도 센서 | 단일 축을 따라 가속 모니터링 |
TYPE_MAGNETIC_FIELD | 자기장 센서 | 나침반 |
TYPE_ORIENTATION | 방향 센서 | 장치 위치 결정 |
TYPE_PRESSURE | 기압 센서 | 공기압 모니터링 변화 |
TYPE_PROXIMITY | 근접 센서 | 통화 중인지 검사 |
TYPE_RELATIVE_HUMIDITY | 상대 습도 센서 | 이슬점, 상대 습도를 모니터링 |
TYPE_ROTATION_VECTOR | 회전 센서 | 모션 감지, 회전 감지 |
TYPE_TEMPERATURE | 온도 센서 | 장치의 온도 감지 |
센서 사용 준비
- SensorManager 인스턴스를 얻는다.
- 위 표에 있는 센서중 하나를 getDefaultSensor() 메서드에 지정하여 Sensor 객체를 얻는다.
- onResume() 메서드에 registerListener() 메서드로 센서의 감지를 등록한다.
- onPause() 메서드에서 unregisterListener() 메서드로 센서의 감지를 해제한다.
// 자신을 SensorEventListener 인터페이스의 구현체로 등록
class MainActivity : AppCompatActivity(), SensorEventListener {
// 1. 지연된 초기화를 사용하여 sensorManager 객체를 얻는다.
private val sensorManager by lazy {
getSystemService(Context.SENSOR_SERVICE) as SensorManager
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
/* 2. registerListener로 사용할 센서를 등록한다.
첫 번째 인자 : 센서값을 받을 SensorEventListener
두 번째 인자 : 센서 종류 지정 getDefaultSensor
세 번째 인자 : 센서 값을 얼마나 자주 받을지 지정
- SENSOR_DELAY_FASTAST : 가능한 가장 자주 센서값을 얻습니다.
- SENSOR_DELAY_GAME : 게임에 적합한 정도로 센서값을 얻습니다.
- SENSOR_DELAY_NORMAL : 화면방향이 전환될 때 적합한 정도로 센서값을 얻습니다.
- SENSOR_DELAY_UI : 사용자 인터페이스를 표시하기에 적합한 정도로 센서값을 얻습니다.
*/
override fun onResume() {
super.onResume()
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL
)
}
// 3. unregisterListener로 센서 사용을 해제한다.
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
// SensorEventListener 인터페이스에서 구현해야 할 메서드
// 센서 정밀도가 변경되면 호출
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
TODO("Not yet implemented")
}
// 센서 값이 변경 되면 호출
override fun onSensorChanged(event: SensorEvent?) {
TODO("Not yet implemented")
}
}
좌표 시스템
- 센서 프레임워크에서는 센서값을 나타내는데 x, y, z 표준 3축 좌표계를 사용한다.
- x : 수평
- y : 수직
- z : 화면 바깥쪽
- 3축 좌표계는 다음 센서에서 사용
- 가속도 센서
- 중력 센서
- 자이로 스코프
- 선형 가속도 센서
- 자기장 센서
센서 API에서 사용하는 좌표 시스템 출처 : https://developer.android.com/guide/topics/sensors/sensors_overview
가속도 센서값 사용하기
// 자신을 SensorEventListener 인터페이스의 구현체로 등록
class MainActivity : AppCompatActivity(), SensorEventListener {
// 1. 지연된 초기화를 사용하여 sensorManager 객체를 얻는다.
....
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
....
// 2. registerListener로 사용할 센서를 등록한다.
....
// 3. unregisterListener로 센서 사용을 해제한다.
....
// SensorEventListener 인터페이스에서 구현해야 할 메서드
// 센서 값이 변경 되면 호출
override fun onSensorChanged(event: SensorEvent?) {
/*
SensorEvent.values[0] : x 축 값 - 위로 기울이면 -10 ~ 0, 아래로 기울이면 0 ~ 10
SensorEvent.values[1] : y 축 값 - 왼쪽으로 기울이면 -10 ~ 0, 오른쪽으로 기울이면 0 ~ 10
SensorEvent.values[2] : z 축 값 - 미사용
*/
event?.let {
Log.d("MainActivity;"
,"onChanged: x: ${event.values[0]}, y: ${event.values[1]}, z: ${event.values[2]}" )
}
}
// 센서 정밀도가 변경되면 호출
....
}
디버그용 메서드
- Log.d( [태그] [, 메시지] )
- 태그 : 로그캣에는 많은 내용이 표시되므로 필터링 할 때 사용
- 메시지 : 출력할 메시지를 작성한다.
- Log 메서드의 종류
- Log.e : 에러를 표시할 때 사용
- Log.w : 경고를 표시할 때 사용
- Log.i : 정보성 로그를 표시할 때 사용
- Log.v : 모든 로그를 표시할 때 사용
가로 고정 및 화면 꺼지지 않게 하기
// 자신을 SensorEventListener 인터페이스의 구현체로 등록
class MainActivity : AppCompatActivity(), SensorEventListener {
// 1. 지연된 초기화를 사용하여 sensorManager 객체를 얻는다.
....
override fun onCreate(savedInstanceState: Bundle?) {
// 화면이 꺼지지 않게 하기
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
// 화면이 가로모드로 고정되게 하기
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
....
// 2. registerListener로 사용할 센서를 등록한다.
....
// 3. unregisterListener로 센서 사용을 해제한다.
....
// SensorEventListener 인터페이스에서 구현해야 할 메서드
// 센서 값이 변경 되면 호출
....
// 센서 정밀도가 변경되면 호출
....
}
에뮬레이터에서 센서 테스트 하기
다음 순서대로 선택하여 ④에서 마우스로 클릭한 상태에서 움직여 보며 테스트 할 수 있다.
스텝3 커스텀 뷰 작성하기
다음과 같이 TiltView를 생성하고 onDraw 메서드를 오버라이드 한다.
package abstractask.example.tiltsensor
import android.content.Context
import android.view.View
class TiltView(context: Context?) : View(context) {
override fun onDraw(canvas: Canvas?) {
}
}
MainActivity 에서는 TiltView 를 사용할 수 있도록 다음과 같이 작성한다.
// 자신을 SensorEventListener 인터페이스의 구현체로 등록
class MainActivity : AppCompatActivity(), SensorEventListener {
// 1. 지연된 초기화를 사용하여 sensorManager 객체를 얻는다.
....
private lateinit var tiltView: TiltView
override fun onCreate(savedInstanceState: Bundle?) {
// 화면이 꺼지지 않게 하기
....
// 화면이 가로모드로 고정되게 하기
....
// 커스텀 뷰 사용하기
tiltView = TiltView(this)
setContentView(tiltView)
}
....
// 2. registerListener로 사용할 센서를 등록한다.
....
// 3. unregisterListener로 센서 사용을 해제한다.
....
// SensorEventListener 인터페이스에서 구현해야 할 메서드
// 센서 값이 변경 되면 호출
....
// 센서 정밀도가 변경되면 호출
....
}
그래픽 API를 다루는 기초
- Canvas : 도화지 (뷰의 표면)
- drawCircle(cx : Float, cy: Float, radius: Float, paint: Paint! )
- cx : X좌표
- cy : Y좌표
- radius : 반지름
- paint : Paint객체
- drawLine(startX: Float, startY: Float, stopX: Float, stopY: Float, paint: Paint!)
- startX : 한 점의 X좌표
- startY : 한 점의 Y좌표
- stopX : 다른 점의 X좌표
- stopY : 다른 점의 Y좌표
- paint : Paint 객체
- drawCircle(cx : Float, cy: Float, radius: Float, paint: Paint! )
- Paint : 붓 (색, 굵기, 스타일 정의)
class TiltView(context: Context?) : View(context) {
private val greenPaint: Paint = Paint()
private val blackPaint: Paint = Paint()
init {
// 녹색 페인트
greenPaint.color = Color.GREEN
// 검은색 테두리 페인트
/*
- FILL : 색을 채움. 획 관련된 설정을 무시
- FILL_AND_STROKE : 획과 관련된 설정을 유지하면서 책을 채움
- STROKE : 화 관련 설정을 유지하여 외관선만 그림
*/
blackPaint.style = Paint.Style.STROKE
}
....
}
수평계 그래픽 구상, 센서 값을 뷰에 반영하기
package abstractask.example.tiltsensor
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.view.View
class TiltView(context: Context?) : View(context) {
private val greenPaint: Paint = Paint()
private val blackPaint: Paint = Paint()
private var cX: Float = 0f
private var cY: Float = 0f
//
private var xCoord: Float = 0f
private var yCoord: Float = 0f
init {
// 녹색 페인트
greenPaint.color = Color.GREEN
// 검은색 테두리 페인트
/*
- FILL : 색을 채움. 획 관련된 설정을 무시
- FILL_AND_STROKE : 획과 관련된 설정을 유지하면서 책을 채움
- STROKE : 화 관련 설정을 유지하여 외관선만 그림
*/
blackPaint.style = Paint.Style.STROKE
}
// 뷰의 크기가 변경될 때마다 호출
/*
- w : 변경된 가로 길이
- h : 변경된 세로 길이
- oldw : 변경 전 가로 길이
- oldh : 변경 전 세로 길이
*/
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
cX = w / 2f
cY = h / 2f
}
override fun onDraw(canvas: Canvas?) {
// 바깥 원
canvas?.drawCircle(cX, cY, 100f, blackPaint)
// 녹색 원
canvas?.drawCircle(xCoord + cX, yCoord + cY, 100f, greenPaint)
// 가운데 십자가
canvas?.drawLine(cX - 20, cY, cX + 20, cY, blackPaint)
canvas?.drawLine( cX, cY - 20 , cX, cY + 20, blackPaint)
}
// MainActivity 에서 호출하여 View에 반영되도록 함수 작성
// onSensorChanged 함수에서 호출됨
fun onSensorEvent( event: SensorEvent) {
// 화면을 가로로 돌렸으므로 X축과 Y축을 서로 바꿈
xCoord = event.values[0] * 20
yCoord = event.values[1] * 20
invalidate()
}
}
MainActivity.onSensorChanged 에서 TiltView.onSensorEvent 호출
// 자신을 SensorEventListener 인터페이스의 구현체로 등록
class MainActivity : AppCompatActivity(), SensorEventListener {
// 1. 지연된 초기화를 사용하여 sensorManager 객체를 얻는다.
....
override fun onCreate(savedInstanceState: Bundle?) {
// 화면이 꺼지지 않게 하기
....
// 화면이 가로모드로 고정되게 하기
....
// 커스텀 뷰 사용하기
....
}
....
// 2. registerListener로 사용할 센서를 등록한다.
....
// 3. unregisterListener로 센서 사용을 해제한다.
....
// SensorEventListener 인터페이스에서 구현해야 할 메서드
// 센서 값이 변경 되면 호출
override fun onSensorChanged(event: SensorEvent?) {
/*
SensorEvent.values[0] : x 축 값 - 위로 기울이면 -10 ~ 0, 아래로 기울이면 0 ~ 10
SensorEvent.values[1] : y 축 값 - 왼쪽으로 기울이면 -10 ~ 0, 오른쪽으로 기울이면 0 ~ 10
SensorEvent.values[2] : z 축 값 - 미사용
*/
event?.let {
....
tiltView.onSensorEvent(event)
}
}
// 센서 정밀도가 변경되면 호출
....
}
결과
'책 > 오준석의 안드로이드 생존코딩 코틀린편' 카테고리의 다른 글
11. 손전등 (0) | 2020.06.23 |
---|---|
10. 지도와 GPS (0) | 2020.06.21 |
7. 나만의 웹 브라우저 (0) | 2020.06.15 |
6. 스톱워치 (0) | 2020.06.11 |
5. 비만도 계산기 (0) | 2020.06.09 |