이번에 신규 기능을 추가하기로 했다.
대충 배달어플에서 라이더가 목적지에 근접하게되면 판매자나 소비자에게 곧 도착한다는 알림을 전송하는 기능을 만들어 보자는 내용
앱 네비에서 어차피 경로를 표시해 주니깐 거기서 몇 미터 남았을때 호출할까.. 아니면 일정 범위를 설정한 뒤, 해당 범위 내에 접근하면 무조건 호출할까 고민 좀 했다.
어느 길로 가든 일단 인접하면 연락이 가게하는게 맞다고 생각되어 후자로 선택
그럼 해당 범위에 들어갔는지 계산하는 함수가 필요한데..
여기서는 헤버사인(Haversine) 공식을 사용하는게 좋다.
지구상의 두 지점간의 거리를 계산할때 사용되는 공식이며, 일반적으로 위도(latitude)와 경도(longitude)를 사용해서 두 지점간의 최단 거리(대원의 호)를 계산한다.
수식은 다음과 같다.
a = sin²(Δlat/2) + cos(lat1) ⋅ cos(lat2) ⋅ sin²(Δlong/2)
c = 2 ⋅ atan2(√a, √(1−a))
d = R ⋅ c
여기서 Δlat는 두 위도 간의 차이, Δlong는 두 경도 간의 차이, R은 지구의 반지름 (일반적으로 평균 반지름 6,371km 사용), d는 두 지점 간의 거리다.
이걸 그대로 구현하면 좋겠으나, 그렇게 정밀하게 계산을 할 필요는 없다고 생각되어 조금 변형된 형태로 코드를 작성하기로 했다.
기본적인 위치 서비스나 거리 추정에서는 크게 문제되지 않는다고 생각한다.
private fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
val lngDifference = lon1 - lon2
val radLat1 = degToRad(lat1)
val radLat2 = degToRad(lat2)
val radLonDiff = degToRad(lngDifference)
var dist = sin(radLat1) * sin(radLat2) + cos(radLat1) * cos(radLat2) * cos(radLonDiff)
dist = acos(dist)
dist = radToDeg(dist)
dist *= 60 * 1.1515
return dist * (1.609344f * 1000)
}
private fun degToRad(deg: Double): Double {
return deg * Math.PI / 180.0
}
private fun radToDeg(rad: Double): Double {
return rad * 180.0 / Math.PI
}
위는 내가 작성한 해버사인 함수다.
대충 내가 설정한 범위랑 비교해서, 위 공식으로 도출된 값이 더 작으면 알림을 쏘게했다.
[사용 예시]
fun checkDistance() : Boolean{
val range = 100
val distance =
calculateDistance(
10,
10,
8,
8
)
return if(distance > range) True else False
}
'Android > Troubleshooting' 카테고리의 다른 글
ROOM DB 마이그레이션 오류 개선 (1) | 2023.12.18 |
---|---|
BuildConfig가 생성 또는 import가 안될 때 (1) | 2023.12.15 |
코루틴 작업 분리 (0) | 2023.11.28 |
Data Class의 equals와 hashCode를 사용해 DB 갱신하기 (1) | 2023.11.27 |
ForegroundService 문제 해결하기: ForegroundServiceDidNotStartInTimeException (7) | 2023.10.30 |