이는 G.IT 와글와글 해커톤 때 있었던 해프닝을 정리한 글입니다.
해커톤의 주제는 '학교 생활과 접목하는 IT'였다.
우리팀은 항상 수업만 들으러 다니고, 학교를 잘 걸어다니지 않는 학생들을 위해 매일 3개씩 학교 안에서 할 수 있는 미션을 제공하고, 만보기를 통해 경험치를 쌓을 수 있는, 다마고치 앱을 기획했다. 레벨이 올라갈 때마다 우리 학교의 마스코트를 알에서부터 진화시킬 수 있도록, 캐릭터 디자인까지 했었다.
원래는 만보기 기능으로 지도에 내 위치를 실시간으로 받아와서 표시하고, 걸음수를 기록하는 것이 주요 기능이었다. 하지만 1박 2일의 짧은 기간 내에 구현하기엔 무리일 거 같아 지도에 내 위치를 표시하는 걸로만 바뀌게 되었다.
근데 그렇게 기능을 없애고, 메인 화면에 있는 맵에서 딱 내 위치 하나만 뜨면 화면이 너무 심심할 것 같았고, 서버 파트분께 미션과 함께 위도 경도를 보내줄 수 있냐고 부탁드렸다. 아무래도 프론트에서 보여줄 기능이 좀 있어야 하니까...
서버 분께서 학교 건물들의 위도, 경도를 다 보내주시고 확인했더니 위의 사진처럼 핀이 잘 찍히는 걸 확인할 수 있었다!
그렇다면 코드를 한 번 살펴보자.
** 카카오맵은 불러왔다는 걸 전제로 그 이후부터 설명
lateinit var mapView: MapView
private lateinit var mapViewContainer : ViewGroup
private var uLatitude : Double = 0.0
private var uLongitude : Double = 0.0
override fun onCreate() {
super.onCreate()
// 위치 권한 허용
getLocationPermission()
// 맵뷰 표시
initMapView()
// 지도가 현재 위치로 표시
setCurrentLocaion()
}
private fun initMapView() {
mapView = MapView(this)
mapViewContainer = binding.activityMainKakaoMapView
mapViewContainer.addView(mapView)
// 줌 레벨 변경
mapView.setZoomLevel(1, true)
}
private fun setCurrentLocation() {
val uNowPosition = MapPoint.mapPointWithGeoCoord(uLatitude, uLongitude)
mapView.setMapCenterPoint(uNowPosition, true)
Log.d("Map", "${uLatitude}, ${uLongitude}")
}
private fun getLocationPermission() {
val permissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION
)
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "위치 권한이 없습니다.", Toast.LENGTH_SHORT).show()
finish()
return
}
val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
try {
val userNowLocation : Location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)!!
uLatitude = userNowLocation.latitude
uLongitude = userNowLocation.longitude
} catch (e : NullPointerException) {
Log.e("LOCATION_ERROR", e.toString())
ActivityCompat.finishAffinity(this)
finish()
}
}
private fun addCustomMarker() {
// 현재 위치에 마커 추가
val marker = MapPOIItem()
marker.apply {
itemName = "현재 위치" // 마커 이름
mapPoint = MapPoint.mapPointWithGeoCoord(uLatitude, uLongitude) // 좌표
markerType = MapPOIItem.MarkerType.CustomImage // 마커 모양 (커스텀)
customImageResourceId = R.drawable.ic_custom_marker // 커스텀 마커 이미지
selectedMarkerType = MapPOIItem.MarkerType.CustomImage // 클릭 시 마커 모양 (커스텀)
selectedMarkerType = MapPOIItem.MarkerType.RedPin // 클릭 시 마커 이미지
isCustomImageAutoscale = false // 커스텀 마커 이미지 크기 자동 조정
setCustomImageAnchor(0.5f, 1.0f) // 마커 이미지 기준점
}
mapView.addPOIItem(marker)
}
현재 위치에는 빨간색 원형 모양의 마커를 달아줬다. customImageResourceId
의 R.drawable.ic_custom_marker가 그 내용이다.
data class MissionMapData(
var missionId: Long,
var missionName: String? = null, // 미션 이름
var latitude: Double, // 위도
var longitude: Double // 경도
)
서버에서 미션이 오는 형태
미션 아이디와 미션명, 그리고 위도와 경도가 같이 온다.
private var missionMapData = ArrayList<MissionMapData>()
private fun setMissionMark(dataList: ArrayList<MissionMapData>) {
for (data in dataList) {
val marker = MapPOIItem()
marker.apply {
itemName = data.missionName
mapPoint = MapPoint.mapPointWithGeoCoord(data.latitude, data.longitude)
// markerType = MapPOIItem.MarkerType.BluePin
selectedMarkerType = MapPOIItem.MarkerType.RedPin
}
mapView.addPOIItem(marker)
}
}
missionMapData
에는 서버에서 받아온 response를 넣어주면 된다.markType
은 기본이 BluePin이라 주석 처리해두었고,selectedMarkerType
는 Redpin으로 설정해주었다.위의 사진을 보면,
- 현재 위치는 빨간색 원으로 표시
- 미션 핀은 BluePin으로 표시
- 선택된 미션 핀은 RedPin으로 표시 + 미션 내용 보여주기
조건을 모두 만족하는 것을 확인할 수 있다!
카카오맵을 직접 써본 것은 처음인데, 학교 내의 여러 장소에 대한 핀을 찍어보니 재밌었다.