갤럭시 워치에 버스 도착 정보를 띄우자!(3) - 카카오맵 다루기

김흰돌·2023년 6월 6일
0

버스 정류장을 지도에 띄우기 위해 네이버 지도, 카카오맵, 구글맵 중 어떤 걸 사용할까 고민했다.

구글맵은 이전 프로젝트에서 사용해 봤기 때문에 이번엔 카카오맵을 사용해보았다.

카카오맵을 내 안드로이드 프로젝트에 띄우는 법은 많은 블로그에 글들이 있으니 이번엔 내가 사용한 카카오맵 기능들을 작성해보려고 한다.

일단 위 스크린 샷을 보면 생각나는 기능은
위치 검색, 마커로 내 위치 표시, 버스 정류장 표시, 현재 내 위치로 이동할 수 있는 버튼이 있다.

먼저 위치 검색부터 어떻게 구현했는지 소개하면



위치 검색

카카오맵 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 객체를 생성하여 카카오에서 제공하는 여러 함수를 사용할 수 있다.

  • itemName으로 마커의 이름을 설정
  • mapPoint로 마커가 생성될 위도와 경도를 설정
  • markerType으로 마커의 기본 모양을 설정
  • selectedMarkerType으로 마커가 선택되었을 시 마커의 모양을 설정

추가로 받아온 버스 정류장 정보를 카카오맵에 띄우기 위해 버스 정류소 이미지를 마커로 띄우고 싶어 아래와 같은 함수를 추가했다.

  • customImageResourceId는 카카오에서 제공하는 마커 이미지 대신 내가 원하는 이미지를 설정할 수 있음
  • customSelectedImageResourceId 마찬가지로 마커가 선택되었을 시 마커의 모양을 설정

더 자세한 내용은 카카오 지도 API Document 참고



내 위치로 이동

내 위치로 이동 버튼을 클릭하면, 내 위치 관련 위도와 경도 정보를 얻어오고 그 정보를 가지고 카카오맵의 시점을 현재 내 위치로 이동해야한다.

mapView.setMapCenterPoint(MapPoint.mapPointWithGeoCoord(latitude, longitude), true);

mapPointWithGeoCoord()에 위도와 경도를 입력해주고 setMapCenterPoint()로 시점을 옮기는 방식으로 작성하면 카카오맵이 현재 내 위치로 이동할 수 있다.

전체 코드 보기



다음 포스팅은 공공데이터를 이용해 버스 정류소 관련 정보를 가져오고 각각의 버스 정류소에 버스 도착 정보를 출력하는 방법을 기록할 예정이다.

0개의 댓글