Sensors API는 기기의 하드웨어 센서에 액세스하기 위한 Android 플랫폼 인터페이스입니다. API는 가속도계, 자이로스코프, 자기계, 조도 센서 및 기타 센서에서 데이터를 얻는 통합된 방법을 제공합니다. Google, 2026에 따르면 최신 Android 기기의 95% 이상이 최소 3가지 유형의 센서를 갖추고 있어 컨텍스트 인식 애플리케이션 개발에 폭넓은 기회를 제공합니다.
주요 내용
Sensors API는 개발자에게 모바일 기기의 하드웨어 센서에 대한 액세스를 제공하는 Android Framework의 소프트웨어 인터페이스입니다. API는 버전 1.0부터 Android SDK의 일부이며 android.hardware 패키지를 통해 사용할 수 있습니다. 이 인터페이스는 Qualcomm, MediaTek, Samsung Exynos 등 다양한 제조업체의 센서 구현 간 차이를 추상화하고 센서 작업을 위한 통합 모델을 제공합니다.
API는 세 가지 주요 작업을 허용합니다: 사용 가능한 센서 목록 가져오기, 데이터 수신을 위한 리스너 등록, 업데이트 속도 관리. SensorManager는 모든 작업의 중앙 액세스 지점 역할을 합니다. 시스템은 onSensorChanged 콜백을 통해 애플리케이션에 알리고 float 값 배열이 포함된 SensorEvent 객체를 전달합니다.
Android의 역사를 통해 API는 여러 개발 단계를 거쳤습니다. 버전 2.3(Gingerbread)에서는 배치 처리(전력 소비를 줄이기 위한 센서 이벤트 그룹화) 지원이 도입되었습니다. Android 4.0(Ice Cream Sandwich)에서는 가상 센서 Gravity와 Linear Acceleration이 추가되었습니다. Android 8.0부터 시스템은 개인정보 보호를 강화하기 위해 센서에 대한 백그라운드 액세스를 제한했습니다.
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensorList: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
sensorList.forEach { sensor ->
Log.d("센서", "${sensor.name} — ${sensor.type}")
}
모든 기기가 동일한 센서 세트를 가지고 있는 것은 아닙니다. 애플리케이션은 리스너를 등록하기 전에 특정 센서의 가용성을 확인해야 합니다. Android 에뮬레이터는 제한된 센서 세트(가속도계와 자기계)만 지원합니다. 다른 센서를 테스트하려면 물리적 기기가 필요합니다. Android 12부터 애플리케이션은 매니페스트에서 센서 사용을 선언해야 합니다.
Android는 모든 센서를 Motion, Position, Environment의 세 가지 범주로 분류합니다. Motion 센서에는 가속도계, 자이로스코프, 만보계가 포함됩니다. Position 센서에는 자기계와 방향이 포함됩니다. Environment 센서에는 조도, 압력, 온도, 습도가 포함됩니다.
| 범주 | 센서 | 유형(상수) | 물리적/가상 |
|---|---|---|---|
| Motion | 가속도계 | TYPE_ACCELEROMETER | 물리적 |
| Motion | 자이로스코프 | TYPE_GYROSCOPE | 물리적 |
| Motion | 만보계 | TYPE_STEP_COUNTER | 물리적 |
| Motion | Gravity | TYPE_GRAVITY | 가상 |
| Position | 자기계 | TYPE_MAGNETIC_FIELD | 물리적 |
| Position | Rotation Vector | TYPE_ROTATION_VECTOR | 가상 |
| Environment | 조도 | TYPE_LIGHT | 물리적 |
| Environment | 압력 | TYPE_PRESSURE | 물리적 |
가속도계는 X, Y, Z의 세 축을 따라 m/s² 단위로 가속도를 측정합니다. 값에는 중력(정지 시 Z축 방향으로 9.8m/s²)이 포함됩니다. 자이로스코프는 각 축을 중심으로 한 기기의 회전 속도인 각속도를 rad/s 단위로 측정합니다. 이 두 센서의 조합은 내비게이션, 게임 및 AR 애플리케이션에서 사용됩니다.
class SensorActivity : Activity(), SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
textView.text = "X: $x, Y: $y, Z: $z"
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
자기계(TYPE_MAGNETIC_FIELD)는 세 축을 따라 마이크로테슬라(µT) 단위로 자기장을 측정합니다. 디지털 나침반으로 사용되며 가속도계와 결합하여 기기의 방위각을 결정합니다. Rotation Vector는 자이로스코프, 가속도계, 자기계의 데이터를 융합하여 정확한 방향을 결정하는 가상 센서입니다.
조도 센서(TYPE_LIGHT)는 럭스(lx) 단위로 주변 조도 수준을 측정합니다. 자동 화면 밝기 조정에 사용됩니다. 압력 센서(TYPE_PRESSURE)는 헥토파스칼(hPa) 단위로 대기압을 측정하며 내비게이션 애플리케이션에서 해발 고도 결정에 사용됩니다.
Sensors API는 클라이언트-서버 아키텍처를 기반으로 구축되었습니다. 애플리케이션은 클라이언트로, SensorManager는 Android 시스템 서비스로 작동합니다. 애플리케이션이 registerListener를 통해 리스너를 등록하면 SensorManager는 HAL(하드웨어 추상화 계층) — Linux 커널 수준에서 실행되는 저수준 센서 드라이버와 통신합니다.
HAL 드라이버는 하드웨어 칩에서 원시 데이터를 수신하고 노이즈를 필터링한 후 스택 위로 — SensorService(시스템 프로세스)를 통해 애플리케이션으로 전달합니다. 데이터는 float 값 배열 values와 나노초 단위의 타임스탬프가 포함된 SensorEvent 객체로 전달됩니다. 이벤트 속도는 선택한 전달 모드에 따라 다릅니다.
리스너 등록 시 개발자는 상수 SENSOR_DELAY_NORMAL(200ms), SENSOR_DELAY_UI(60ms), SENSOR_DELAY_GAME(20ms), SENSOR_DELAY_FASTEST(0ms — 최대 속도)를 사용하여 이벤트 간 원하는 지연 시간을 지정합니다. 실제 속도는 다를 수 있으며 시스템이 전력 소비를 최적화합니다.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
this,
sensor,
SensorManager.SENSOR_DELAY_GAME
)
Android 2.3부터 센서는 배치 모드를 지원합니다 — 이벤트가 FIFO 버퍼에 축적되어 단일 배치로 전달됩니다. 이를 통해 프로세서가 절전 모드에 더 오래 머물러 전력 소비를 최대 60%까지 줄일 수 있습니다. 버퍼 크기는 센서 칩에 따라 다르며 Sensor.fifoMaxEventCount 필드에 지정됩니다.
SensorManager는 getSystemService(Context.SENSOR_SERVICE)를 통해 사용할 수 있는 시스템 서비스입니다. 센서 목록 가져오기, 특정 기본 센서 가져오기, 리스너 등록/해제 메서드를 제공합니다. SensorManager는 싱글톤으로 애플리케이션 전체에 하나의 인스턴스만 있습니다.
센서를 사용하기 전에 가용성을 확인해야 합니다. getDefaultSensor(type) 메서드는 센서가 기기에 없는 경우 null을 반환합니다. 확인 없이 null을 얻으면 리스너 등록 시 NullPointerException이 발생합니다. getSensorList(type) 메서드는 모든 센서의 목록을 반환합니다.
fun checkSensorAvailability(type: Int): Boolean {
val sensorManager =
getSystemService(Context.SENSOR_SERVICE) as SensorManager
return sensorManager.getDefaultSensor(type) != null
}
// 사용법:
if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
Log.d("센서", "자이로스코프 사용 가능")
}
리스너는 registerListener(listener, sensor, delay)를 통해 등록됩니다. 중요: onPause() 메서드에서 unregisterListener(listener)를 통해 리스너를 해제해야 합니다. 그렇지 않으면 애플리케이션이 백그라운드에서도 센서 이벤트를 계속 수신하여 배터리를 소모합니다. Android 8+는 해제되지 않은 리스너에 대해 logcat에 경고를 표시합니다.
onAccuracyChanged(sensor, accuracy) 메서드는 센서 정확도가 변경될 때 호출됩니다. 값: SENSOR_STATUS_ACCURACY_HIGH, MEDIUM, LOW, UNRELIABLE. UNRELIABLE 수신 시 정확도가 복원될 때까지 센서 데이터를 무시해야 합니다. 예를 들어 자기계는 보정(기기를 8자 모양으로 흔들기)이 필요합니다.
Kotlin을 사용한 Android 애플리케이션에서 Sensors API 사용의 실제 예제를 살펴보겠습니다. 첫 번째 예제 — 가속도계를 사용한 화면 방향 결정. 두 번째 — 보정 기능이 있는 자기계 데이터 읽기. 세 번째 — 만보계를 사용한 걸음 감지기.
방향을 결정하기 위해 가속도계와 자기계의 조합이 사용됩니다. SensorManager.getRotationMatrix() 메서드는 회전 행렬을 계산하고 getOrientation()은 pitch, roll, azimuth 각도를 추출합니다. Azimuth(방위각) — 라디안 단위의 자기 북쪽에 대한 각도입니다.
val gravity = FloatArray(3)
val geomagnetic = FloatArray(3)
val rotationMatrix = FloatArray(9)
val orientation = FloatArray(3)
SensorManager.getRotationMatrix(
rotationMatrix, null, gravity, geomagnetic
)
SensorManager.getOrientation(rotationMatrix, orientation)
// orientation[0] — azimuth, [1] — pitch, [2] — roll
val azimuthDeg = Math.toDegrees(orientation[0].toDouble())
만보계(TYPE_STEP_COUNTER)는 마지막 기기 재시작 이후 사용자가 걸은 총 걸음 수를 반환합니다. 센서는 하드웨어 수준에서 작동하며 애플리케이션이 실행되지 않는 경우에도 활성 상태를 유지합니다. 세션당 걸음 수를 얻으려면 초기 값을 저장하고 차이를 계산해야 합니다.
var initialSteps = 0
var isInitialized = false
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
if (!isInitialized) {
initialSteps = event.values[0].toInt()
isInitialized = true
}
val currentSteps = event.values[0].toInt()
val sessionSteps = currentSteps - initialSteps
Log.d("걸음", "세션당 걸음 수: $sessionSteps")
}
}
조도 센서는 인터페이스를 환경 조건에 적응시킬 수 있습니다. 저조도(10lx 미만)에서는 다크 모드로 전환할 수 있습니다. 밝은 햇빛(10000lx 이상)에서는 대비를 높일 수 있습니다. 노이즈 필터링에는 마지막 5개 값의 이동 평균이 사용됩니다.
Android는 직접적인 하드웨어에 해당하는 것이 없는 여러 가상 센서를 제공합니다. 가상 센서는 물리적 센서의 조합을 기반으로 판독값을 계산합니다. 이는 개발자의 부담을 줄여줍니다 — 시스템 자체가 데이터 융합 알고리즘을 구현합니다.
Gravity(TYPE_GRAVITY) 센서는 저역 통과 필터를 사용하여 가속도계 판독값에서 중력 성분을 추출합니다. Linear Acceleration(TYPE_LINEAR_ACCELERATION)은 반대로 중력을 제거하고 기기의 선형 가속도만 남깁니다. Gravity와 Linear Acceleration의 합은 가속도계의 원시 판독값을 제공합니다.
Rotation Vector — 가장 복잡한 가상 센서입니다. 자이로스코프(고주파 변화), 가속도계(중력 벡터), 자기계(북쪽에 대한 방향)의 데이터를 결합합니다. 결과는 공간에서 기기의 절대 방향을 설명하는 쿼터니언입니다. AR 애플리케이션과 VR 헤드셋에서 사용됩니다.
Game Rotation Vector — 자기계를 사용하지 않는 Rotation Vector의 단순화된 버전입니다. 방위각 정확도는 낮아지지만 업데이트 속도와 안정성이 향상됩니다. 북쪽에 대한 절대 방향보다 낮은 지연 시간이 중요한 게임에 권장됩니다.
센서는 기기에서 가장 전력을 많이 소비하는 구성 요소 중 하나입니다. 최대 폴링 속도에서 가속도계와 자이로스코프는 3–4시간의 연속 작동으로 배터리를 방전시킬 수 있습니다. 센서 사용 최적화는 Sensors API를 사용하는 모든 애플리케이션의 중요한 과제입니다.
불필요하게 SENSOR_DELAY_FASTEST를 사용하지 마십시오. UI 애니메이션에는 SENSOR_DELAY_UI(60ms)로 충분합니다. 화면 방향 감지에는 SENSOR_DELAY_NORMAL(200ms)로 충분합니다. 속도가 높을수록 프로세서가 활성 상태에 머무는 시간이 길어집니다. NORMAL과 FASTEST 간의 전력 소비 차이는 최대 10배입니다.
Android 8.0(API 26)부터 백그라운드 애플리케이션은 감소된 속도로 센서 이벤트를 수신합니다. Android 12+에서는 Motion 및 Position 센서에 대한 백그라운드 액세스에 BODY_SENSORS_BACKGROUND 권한이 필요합니다. 애플리케이션이 백그라운드로 전환될 때 리스너를 해제하면 기기 배터리 수명이 연장됩니다.
registerListener(listener, sensor, delay, maxReportLatencyUs) 메서드를 통해 배치 처리를 사용합니다. maxReportLatencyUs 매개변수는 마이크로초 단위의 최대 이벤트 전달 지연 시간을 설정합니다. 1000000(1초) 값의 경우 이벤트가 센서의 FIFO 버퍼에 축적되어 초당 한 번 전달되므로 프로세서가 덜 자주 깨어납니다.
자주 묻는 질문
최소 세트는 가속도계와 자기계입니다. 이 두 센서는 기기의 95% 이상에 있습니다. 자이로스코프, 조도 센서, 근접 센서는 최신 모델의 70–80%에 있습니다. 기타 센서(압력, 온도, 습도, 만보계)는 덜 일반적이며 기기의 가격대에 따라 다릅니다.
TYPE_ACCELEROMETER는 중력(9.8m/s²)을 포함한 전체 가속도를 반환합니다. TYPE_LINEAR_ACCELERATION은 중력을 제외한 가속도, 즉 기기 동작의 가속도만 반환합니다. 기기가 정지해 있는 경우 가속도계는 Z축을 따라 9.8m/s²를 표시하는 반면 Linear Acceleration은 모든 축에서 0을 표시합니다.
적절한 상수와 함께 getPackageManager().hasSystemFeature()를 사용하세요: FEATURE_SENSOR_ACCELEROMETER, FEATURE_SENSOR_GYROSCOPE, FEATURE_SENSOR_PROXIMITY 등. 다른 방법으로는 getDefaultSensor(type)을 호출하고 결과가 null인지 확인하는 것입니다. 초기화 중 확인에는 첫 번째 방법이 더 좋습니다.
센서의 원시 데이터에는 노이즈가 포함되어 있습니다. 평활화를 위해 저역 통과 필터를 사용하세요: newValue = alpha * rawValue + (1 — alpha) * previousValue. alpha 계수 0.1–0.3은 응답성과 평활성 사이의 좋은 균형을 제공합니다. 자이로스코프의 경우 제로 드리프트 제거를 위해 고역 통과 필터도 적용됩니다.
네, 하지만 제한 사항이 있습니다. Android 8.0부터 백그라운드 애플리케이션의 센서 이벤트 속도가 감소합니다. Android 12부터 백그라운드 센서 액세스에 BODY_SENSORS_BACKGROUND 권한이 필요합니다. 백그라운드 작업에는 알림이 있는 Foreground Service를 사용하는 것이 좋습니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.