1. 액티비티 생명주기
- 액티비티 생명주기 (Activity LifeCycle)
- 액티비티는 생성부터 소멸까지 상태가 변한다.
- 안드로이드 시스템이 각 상태에 맞는 콜백(callback) 메서드를 자동으로 호출한다.
- 화면이 작아 한 번에 하나의 액티비티만 활성화되고, 나머지는 스택(Stack)에 비활성 상태로 쌓인다.
1.1. 주요 상태
- 실행(Running): 화면에 보이고 이벤트 처리 가능, 스택 최상위
- 일시 중지(Paused): 다이얼로그 등으로 일부 가려져 보이지만 이벤트 처리 불가
- 중지(Stopped): 다른 액티비티에 완전히 가려져 보이지 않음
1.2. 호출 순서
- 시작:
onCreate()→onStart()→onResume()→ 실행 - 종료:
onPause()→onStop()→onDestroy() - 재개(백그라운드 대기 후 복귀):
onRestart()→onStart()→onResume()
화면이 비활성화된 상태에서도 센서가 동작하면 배터리가 빨리 소모되므로, 생명주기를 숙지해 적절한 타이밍에 센서를 켜고 꺼야 한다.
2. 센서 개요
SensorManager(센서 관리자)를 통해 각종 센서에 접근하고, SensorEventListener로 이벤트를 수신합니다. 센서들의 사용법은 대부분 유사해서 하나만 익히면 응용이 쉽습니다.
2.1. 주요 센서
| 주요 센서 | 용도 |
|---|---|
| TYPE_ACCELEROMETER | 가속도 센서 (흔들림, 기울임 감지) |
| TYPE_GRAVITY | 중력 |
| TYPE_GYROSCOPE | 자이로 센서 (회전 감지) |
| TYPE_LIGHT | 조도 센서 (화면 밝기 제어) |
| TYPE_MAGNETIC_FIELD | 자기장 센서 (나침반) |
| TYPE_PROXIMITY | 근접 센서 (통화 감지) |
| TYPE_PRESSURE | 기압 센서 |
2.2. 센서 사용 과정
- SensorManager 인스턴스 획득
private val sensorManager: SensorManager by lazy { // lazy 초기화 권장
getSystemService(Context.SENSOR_SERVICE) as SensorManager
}-
getDefaultSensor()로 원하는 Sensor 객체 획득 -
onResume()에서registerListener()로 센서 감지 등록
override fun onResume() {
super.onResume()
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL
)
}- 리스너 등록 시 갱신 주기를 지정한다.
SENSOR_DELAY_NORMAL: 일반 (화면 전환용)SENSOR_DELAY_UI: UI용SENSOR_DELAY_GAME: 게임용SENSOR_DELAY_FASTEST: 가장 빠름- 너무 자주 읽으면 리소스·배터리를 낭비한다.
onPause()에서unregisterListener()로 감지 해제
2.3. 구현해야 할 메서드
onSensorChanged()
// 측정값이 변할 때마다 호출
override fun onSensorChanged(event: SensorEvent?) {
event?.let{
Log.d("onSensorChanged", "x: ${event.values[0]}, y: ${event.values[1]}, z: ${event.values[2]}")
}
}- 센서 값은
SensorEvent.values[]배열로 전달된다. - 기기를 정면에서 봤을 때:
SensorEvent.values[0]- x축: 수평, 오른쪽 방향SensorEvent.values[1]- y축: 수직, 위쪽 방향SensorEvent.values[2]- z축: 화면 바깥쪽 방향
onAccuracyChanged()
// 정밀도 변경 시 호출
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}3. 센서를 활용한 수평 측정기 앱 제작
가속도 센서로 기기의 기울기를 측정해, 화면의 녹색 원이 가운데로 오면 수평임을 나타내는 앱이다.
3.1. 기본 설정 (onCreate 내)
// 가로 모드 고정
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
// 화면 꺼짐 방지
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)3.2. 커스텀 뷰 작성
-
View를 상속한TiltView클래스 생성 후onDraw()오버라이드 -
그래픽 API
Canvas: 도화지 (뷰의 표면)Paint: 붓, color·style 지정- Style 옵션: FILL, FILL_AND_STROKE, STROKE
-
drawCircle(cx, cy, radius, paint)로 원,drawLine(...)으로 십자선을 그림 -
onSizeChanged(w, h, oldw, oldh)로 뷰 크기를 받아- → 중점 좌표
cX = w/2,cY = h/2계산 - (안드로이드 좌표는 좌측 상단이 원점)
- → 중점 좌표
3.3. 센서값 반영
- TiltView에
onSensorEvent()메서드 정의- → 가로 모드라 x/y를 반대로 대입하고,
- 값이 작아 ×20 한 뒤
invalidate()로 다시 그림
fun onSensorEvent(event: SensorEvent?) {
yCoord = event!!.values[0] * 20
xCoord = event.values[1] * 20
invalidate()
}- onDraw에서 녹색 원만
(cX + xCoord, cY + yCoord)로 이동시켜 기울기 반영 - MainActivity의
onSensorChanged()에서tiltView.onSensorEvent(event)를 호출하여 값을 전달한다.
4. 에뮬레이터 센서 테스트
- 에뮬레이터 햄버거 메뉴(…) → Virtual sensors → Accelerometer에서 가상으로 기기를 기울여 테스트할 수 있다.
- X축과 y축 값이 0이면 수평 상태이다.