안드로이드 프레임워크·시스템 학습 노트 목차

위치·센서 — FusedLocation·SensorManager·권한 실전

위치는 왜 이렇게 까다로운가

지도·운동·날씨·배달 앱은 기기의 위치와 센서를 읽는다. 그런데 위치는 가장 민감한 권한이다 — 사람이 어디 있는지는 그 사람의 생활 전체를 드러낸다. 그래서 안드로이드는 위치 권한을 단계로 쪼개 사용자가 필요한 만큼만 주게 하고, 동시에 위치·센서는 배터리를 많이 먹는 자원이라 켜 둔 채 잊으면 배터리가 순식간에 닳는다. 이 장의 두 축은 (1) 권한을 최소·단계적으로, (2) 자원을 필요한 동안만 — 둘 다 절제가 핵심이다. [10 권한]을 위치·센서 실전으로 잇는다. (출처: Android — Location / Sensors.)

위치 권한 — 단계적 동의

위치 권한은 정밀도와 시점에 따라 단계가 있고, 사용자가 낮은 단계만 줄 수도 있다 — 앱은 받은 만큼만으로 동작하게 설계해야 한다.

다이어그램 로딩 중…
  • ACCESS_COARSE_LOCATION대략 위치(도시·동네 수준). 정밀이 불필요하면(날씨 같은) 이것만 받는다.
  • ACCESS_FINE_LOCATION정밀 위치(GPS). Android 12+부터 사용자는 "정확/대략" 중 선택할 수 있어, 정확을 요청해도 대략만 줄 수 있다 — 그 경우에도 동작하게 한다.
  • ACCESS_BACKGROUND_LOCATION앱이 안 보일 때도 위치를 받는다. 별도 동의가 필요하고 스토어 심사가 까다롭다지오펜싱·지속 추적이 정말 필요할 때만 받고, 전경에서만 쓰면 절대 받지 마라(신뢰·심사에 불리하다).

요청 흐름은 [10]의 *런타임 권한 3분기(이미 허용 / rationale 표시 / 요청)*를 그대로 따른다.

위치 읽기 — FusedLocationProviderClient

위치를 어디서 읽을까? GPS만 쓰면 실내에서 안 잡히고 배터리를 많이 먹는다. FusedLocationProviderClient(Play Services Location)는 GPS·Wi-Fi·셀룰러·센서를 융합상황에 맞는 정확도·배터리 균형을 자동으로 맞춘다 — 그래서 안드로이드 기본 LocationManager보다 권장된다.

val client = LocationServices.getFusedLocationProviderClient(context)

// 현재 위치 1회 — 정확도/배터리 우선순위를 고른다
val loc = client.getCurrentLocation(Priority.PRIORITY_BALANCED_POWER_ACCURACY, null).await()

// 지속 업데이트 — 5초 간격
val request = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 5_000).build()
client.requestLocationUpdates(request, callback, Looper.getMainLooper())
// ★ 안 쓸 땐 반드시 removeLocationUpdates — 안 그러면 배터리가 계속 닳는다

핵심은 우선순위(Priority)로 정확도와 배터리를 거래하는 것이다 — HIGH_ACCURACY(내비처럼 정밀하나 배터리↑)·BALANCED(일반)·LOW_POWER(도시 수준, 배터리↓). 그리고 *지속 업데이트는 안 쓰는 순간 반드시 removeLocationUpdates*로 끈다 — 켜 둔 채 잊으면 화면이 꺼져도 GPS가 돌아 배터리가 급격히 닳는다.

센서 — SensorManager와 생명주기 짝맞춤

가속도·자이로·근접·조도 같은 센서는 SensorManager리스너를 등록해 읽는다. 여기서 철칙은 — 생명주기에 짝을 맞춰 등록/해제하는 것이다([01]의 자원 짝맞춤).

override fun onResume() {                                          // 화면이 보이기 시작하면
    sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI)
}
override fun onPause() {                                           // 화면이 가려지면
    sensorManager.unregisterListener(this)   // ★ 안 풀면 배터리 소모 + 리스너가 화면을 붙잡아 누수
}

onResume에서 등록하고 onPause에서 해제한다 — 해제를 깜빡하면 화면이 백그라운드로 가도 센서가 계속 콜백을 쏴 배터리를 먹고, 리스너가 Activity를 참조한 채 남아 누수가 된다([12 메모리]). 샘플링 속도(SENSOR_DELAY_FASTEST/GAME/UI/NORMAL)로 정밀도와 전력을 거래한다 — 빠를수록 정밀하지만 배터리를 더 먹는다.

배터리·정확도 — 늘 트레이드오프

위치·센서를 다루는 모든 결정은 정확도와 배터리의 거래다. 그래서 필요한 정확도만, 필요한 동안만 켠다. *"사용자가 특정 지역에 들어왔는지"*만 알면 되면 — *지속 위치 추적 대신 지오펜싱(Geofencing)*이 훨씬 효율적이고, *"걷는 중인지 차에 탔는지"*는 *활동 인식(Activity Recognition)*이 적은 전력으로 알려준다. 백그라운드 위치가 정말 필요하면 WorkManager·포그라운드 서비스([07·02])와 엮어 OS의 백그라운드 제한을 정직하게 따른다.

정리 — 최소 권한·최소 시간으로

위치·센서의 핵심 — 위치 권한은 단계적·최소(COARSE→FINE→BACKGROUND, 전경만 쓰면 BACKGROUND 금지), FusedLocationProviderClient로 정확도↔배터리 우선순위를 고르고 안 쓰면 즉시 해제, 센서는 onResume 등록/onPause 해제로 짝맞춤(안 풀면 배터리·누수), 늘 정확도와 배터리를 거래. 민감하고 배터리 비싼 자원이니 꼭 필요한 만큼·필요한 동안만 쓰는 절제가 전부다.

한 줄 요약 — 위치 권한 단계: COARSE(대략)→FINE(정밀, 12+는 사용자가 정확/대략 선택)→BACKGROUND(별도 동의·전경만이면 금지). FusedLocationProviderClient(getCurrentLocation/requestLocationUpdates)·Priority로 정확도↔배터리·안 쓰면 removeLocationUpdates. 센서는 SensorManager onResume 등록/onPause 해제(안 풀면 배터리·누수)·SENSOR_DELAY로 정밀도↔전력. 지오펜싱/활동 인식이 지속 추적보다 효율적, 백그라운드는 WorkManager/포그라운드 서비스.

(출처: Android — Request location / FusedLocationProvider / Sensors overview / Location permissions.)

이미지·미디어 — Coil·Media3·CameraX배포·인앱·국제화 — Play Store·결제·업데이트·다국어