버스 정류장을 지도에 띄우기 위해 네이버 지도, 카카오맵, 구글맵 중 어떤 걸 사용할까 고민했다.
구글맵은 이전 프로젝트에서 사용해 봤기 때문에 이번엔 카카오맵을 사용해보았다.
카카오맵을 내 안드로이드 프로젝트에 띄우는 법은 많은 블로그에 글들이 있으니 이번엔 내가 사용한 카카오맵 기능들을 작성해보려고 한다.
일단 위 스크린 샷을 보면 생각나는 기능은
위치 검색, 마커로 내 위치 표시, 버스 정류장 표시, 현재 내 위치로 이동할 수 있는 버튼이 있다.
먼저 위치 검색부터 어떻게 구현했는지 소개하면
카카오맵 API에서 지원하는 기능 중 키워드 검색을 사용했다.
REST API 카카오
카카오 API를 사용하기 위해 Hilt 모듈을 만들었다
@Module
@InstallIn(SingletonComponent::class)
object KakaoApiModule {
private const val BASE_URL = "https://dapi.kakao.com"
@Singleton
@Provides
fun provideKakaoService(): KakaoService {
return Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build()
.create(KakaoService::class.java)
}
}
그리고 KakaoService는 아래와 같이 작성했다.
interface KakaoService {
@GET("/v2/local/search/keyword.json")
suspend fun searchPlace(
@Query("query") query: String,
@Query("radius") radius: Int, // 검색 범위를 설정한다 ex) 5000 = 5km 내의 시설 검색
@Query("y") y: Double,
@Query("x") x: Double,
@Header("Authorization") Authorization: String
): KakaoResponse
}
데이터를 받을 data class는 아래와 같이 작성했다.
data class KakaoResponse(
val documents: List<Document>,
val meta: Meta
) {
data class Document(
val address_name: String,
val category_group_code: String,
val category_group_name: String,
val category_name: String,
val distance: String,
val id: String,
val phone: String,
val place_name: String,
val place_url: String,
val road_address_name: String,
val x: String,
val y: String
)
data class Meta(
val is_end: Boolean,
val pageable_count: Int,
val same_name: SameName,
val total_count: Int
) {
data class SameName(
val keyword: String,
val region: List<Any>,
val selected_region: String
)
}
}
Repository를 아래와 같이 작성해주고
class KakaoMapRepositoryImpl @Inject constructor(
private val kakaoService: KakaoService
) : KakaoMapRepository {
override suspend fun searchLocation(
address: String,
latitude: Double,
longitude: Double
): KakaoResponse {
return kakaoService.searchPlace(
address,
5000,
latitude,
longitude,
"KakaoAK adbab23df5d7301de7db6ce10d19ff10"
)
}
}
ViewModel에서 아래와 같이 사용했다.
@HiltViewModel
class MapViewModel @Inject constructor(
private val kakaoMapRepository: KakaoMapRepositoryImpl,
) : ViewModel() {
private val _searchResult = MutableLiveData<KakaoResponse>()
val searchResult: LiveData<KakaoResponse>
get() = _searchResult
fun searchLocation(address: String, latitude: Double, longitude: Double) {
viewModelScope.launch {
_searchResult.value = kakaoMapRepository.searchLocation(address, latitude, longitude)
}
}
}
받아온 검색 결과를 MapActivity에서 사용하면 된다.
mapViewModel.searchResult.observe(this, androidx.lifecycle.Observer {
if (it.documents.isEmpty()) {
Toast.makeText(this, "5km 근방에 찾으신 시설이 없습니다.", Toast.LENGTH_SHORT).show()
} else {
setMarker(
it.documents[0].y.toDouble(),
it.documents[0].x.toDouble(),
it.documents[0].place_name,
)
}
})
그리고 MapActivity에서 setMarker라는 코드를 볼 수 있는데 말 그대로 Marker를 설정하는 함수이다.
private fun setMarker(latitude: Double, longitude: Double, title: String) {
val marker = MapPOIItem()
marker.apply {
itemName = title
mapPoint = MapPoint.mapPointWithGeoCoord(latitude, longitude)
markerType = MapPOIItem.MarkerType.BluePin
selectedMarkerType = MapPOIItem.MarkerType.RedPin
}
mapView.addPOIItem(marker)
}
marker 객체를 생성하여 카카오에서 제공하는 여러 함수를 사용할 수 있다.
추가로 받아온 버스 정류장 정보를 카카오맵에 띄우기 위해 버스 정류소 이미지를 마커로 띄우고 싶어 아래와 같은 함수를 추가했다.
더 자세한 내용은 카카오 지도 API Document 참고
내 위치로 이동 버튼을 클릭하면, 내 위치 관련 위도와 경도 정보를 얻어오고 그 정보를 가지고 카카오맵의 시점을 현재 내 위치로 이동해야한다.
mapView.setMapCenterPoint(MapPoint.mapPointWithGeoCoord(latitude, longitude), true);
mapPointWithGeoCoord()에 위도와 경도를 입력해주고 setMapCenterPoint()로 시점을 옮기는 방식으로 작성하면 카카오맵이 현재 내 위치로 이동할 수 있다.
다음 포스팅은 공공데이터를 이용해 버스 정류소 관련 정보를 가져오고 각각의 버스 정류소에 버스 도착 정보를 출력하는 방법을 기록할 예정이다.