1. 시작하기 전에
Google 지도로 앱을 빌드하면 위성 이미지, 지도를 위한 강력한 UI 컨트롤, 위치 추적, 위치 마커와 같은 기능을 앱에 추가할 수 있습니다. 유명한 낚시 또는 등산 구역의 위치와 같이 자체 데이터 세트의 정보를 표시하여 표준 Google 지도에 가치를 더할 수 있습니다. 보물찾기나 증강 현실 게임과 같이 플레이어가 실제 세계를 탐험하는 게임을 만들 수도 있습니다.
이 강의에서는 맞춤설정된 지도와 사용자의 위치를 보여주는 Wander라는 Google 지도 앱을 만듭니다.
기본 요건
다음 지식:
- Android 스튜디오를 사용하여 기본 Android 앱을 만들고 실행하는 방법
- 문자열과 같은 리소스를 만들고 관리하는 방법
- Android 스튜디오를 사용하여 코드를 리팩터링하고 변수 이름을 바꾸는 방법
- 사용자가 Google 지도를 사용하는 방법
- 런타임 권한을 설정하는 방법
학습할 내용
- Google API 콘솔에서 API 키를 가져와 앱에 등록하는 방법
- 앱에 Google 지도를 통합하는 방법
- 다양한 지도 유형을 표시하는 방법
- Google 지도의 스타일을 지정하는 방법
- 지도에 마커를 추가하는 방법
- 사용자가 관심 장소에 마커를 배치할 수 있도록 하는 방법 (POI)
- 위치 추적을 사용 설정하는 방법
- Google 지도가 삽입된
Wander
앱을 만드는 방법 - 마커 및 스타일 지정과 같은 앱의 맞춤 기능을 만드는 방법
- 앱에서 위치 추적을 사용 설정하는 방법
2. 앱 개요
이 Codelab에서는 맞춤 스타일을 지정하여 Google 지도를 표시하는 Wander
앱을 만듭니다. Wander 앱을 사용하면 위치에 마커를 놓거나 오버레이를 추가하거나 위치를 실시간으로 확인할 수 있습니다.
3. 작업: 프로젝트 설정 및 API 키 가져오기
Android용 Maps SDK를 사용하려면 API 키가 필요합니다. API 키를 가져오려면 프로젝트를 API 및 서비스 페이지를 참조하세요. API 키는 앱을 작성자와 연결하는 디지털 인증서에 연결됩니다. 디지털 인증서 사용 및 앱 서명에 관한 자세한 내용은 앱 서명을 참고하세요.
이 Codelab에서는 디버그 인증서에 API 키를 사용합니다. 디버그 인증서는 디버그 빌드 서명에 설명된 대로, 의도적으로 안전하지 않습니다. Android용 Maps SDK를 사용하는 게시된 Android 앱에는 두 번째 API 키, 즉 출시 인증서용 키가 필요합니다. 출시 인증서 가져오기에 대한 자세한 내용은 API 키 가져오기를 참고하세요.
Android 스튜디오에는 유용한 템플릿 코드를 생성하는 Google Maps Activity 템플릿이 포함되어 있습니다. 템플릿 코드에는 API 키 가져오기를 간소화하는 링크가 포함된 google_maps_api.xml 파일이 포함되어 있습니다.
1단계: 지도 템플릿으로 Wander 프로젝트 만들기
- 새 Android 스튜디오 프로젝트를 만듭니다.
- Google Maps Activity 템플릿을 선택합니다.
- 프로젝트 이름을
Wander
로 지정합니다. - 최소 API 수준을 API 19로 설정합니다. 언어가 Kotlin인지 확인합니다.
- 마침을 클릭합니다.
- 앱 빌드가 완료되면 프로젝트와 Android 스튜디오에서 자동으로 생성되는 다음과 같은 지도 관련 파일을 살펴봅니다.
google_maps_api.xml: 이 구성 파일을 사용하여 API 키를 보관합니다. 이 템플릿은 디버그용과 릴리스용 하나씩, 이렇게 두 개의 google_maps_api.xml 파일을 생성합니다. 디버그 인증서의 API 키 파일은 src/debug/res/values에 있습니다. 출시 인증서의 API 키 파일은 src/release/res/values에 있습니다. 이 Codelab에서는 디버그 인증서만 사용합니다.
activity_maps.xml: 이 레이아웃 파일에는 전체 화면을 채우는 단일 프래그먼트가 포함되어 있습니다. SupportMapFragment
클래스는 Fragment
클래스의 서브클래스입니다. SupportMapFragment
은 앱에 지도를 배치하는 가장 간단한 방법입니다. 필요한 수명 주기 요구사항을 자동으로 처리하기 위한 지도 뷰를 둘러싸는 래퍼입니다.
추가 name
속성과 함께 ViewGroup
에서 <fragment>
태그를 사용하여 레이아웃 파일에 SupportMapFragment
를 포함할 수 있습니다.
android:name="com.google.android.gms.maps.SupportMapFragment"
MapsActivity.java: MapsActivity.java 파일은 onCreate()
메서드의 SupportMapFragment
를 인스턴스화하고 getMapAsync
()
: 지도 시스템과 뷰를 자동으로 초기화합니다. SupportMapFragment
가 포함된 활동은 OnMapReadyCallback
인터페이스와 인터페이스의 onMapReady()
메서드를 구현해야 합니다. onMapReady()
메서드는 지도가 로드될 때 호출됩니다.
2단계: API 키 가져오기
- google_maps_api.xml 파일의 디버그 버전을 엽니다.
- 파일에서 긴 URL이 포함된 댓글을 찾습니다. URL의 매개변수에는 앱에 대한 특정 정보가 포함됩니다.
- URL을 복사하여 브라우저에 붙여넣습니다.
- 안내에 따라 API 및 서비스 페이지를 참조하세요. 제공된 URL의 매개변수로 인해 페이지는 Android용 Maps SDK를 자동으로 사용 설정합니다.
- API 키 만들기를 클릭합니다.
- 다음 페이지에서 API 키 섹션으로 이동하여 방금 만든 키를 클릭합니다.
- 키 제한을 클릭하고 Android용 Maps SDK를 선택하여 키 사용을 Android 앱으로 제한합니다.
- 생성된 API 키를 복사합니다. '
AIza"
'(으)로 시작합니다. google_maps_api.xml
파일에서YOUR_KEY_HERE
라고 표시된google_maps_key
문자열에 키를 붙여넣습니다.- 앱을 실행합니다. 호주 시드니에 설정된 마커가 포함된 삽입된 지도가 활동에 표시됩니다. 시드니 마커는 템플릿의 일부이며 나중에 변경할 수 있습니다.
3단계: mMap 이름 바꾸기
MapsActivity
에는 GoogleMap
유형인 mMap
라는 비공개 lateinit
var
가 있습니다. Kotlin 이름 지정 규칙을 따르려면 mMap
의 이름을 map
로 변경합니다.
MapsActivity
에서mMap
를 마우스 오른쪽 버튼으로 클릭하고 Refactor >를 클릭합니다. 이름 바꾸기...
- 변수 이름을
map
로 변경합니다.
onMapReady()
함수에서 mMap
에 대한 모든 참조도 map
로 변경되는 것을 볼 수 있습니다.
4. 작업: 지도 유형 추가하기
Google 지도에는 일반, 하이브리드, 위성, 지형 및 '없음' 등 여러 지도 유형이 있습니다. (지도가 전혀 없을 때)
일반 맵 | 위성 지도 | 하이브리드 지도 | 지형 지도 |
각 지도 유형은 서로 다른 종류의 정보를 제공합니다. 예를 들어, 자동차에서 내비게이션을 위해 지도를 사용하는 경우 도로 이름을 확인하는 것이 유용하므로 일반 옵션을 사용할 수 있습니다. 하이킹을 할 때 지형 지도는 정상까지 올라가기 위해 얼마나 더 올라가야 하는지 파악하는 데 도움이 될 수 있습니다.
이 작업에서는 다음 작업을 수행합니다.
- 사용자가 지도 유형을 변경할 수 있는 옵션 메뉴가 있는 앱 바를 추가합니다.
- 지도의 시작 위치를 내 집 위치로 이동합니다.
- 지도에서 단일 위치를 나타내고 라벨을 포함할 수 있는 마커 지원을 추가합니다.
지도 유형 메뉴 추가
이 단계에서는 사용자가 지도 유형을 변경할 수 있는 옵션 메뉴가 있는 앱 바를 추가합니다.
- 새 메뉴 XML 파일을 만들려면 res 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 New > Android 리소스 파일.
- 대화상자에서 파일 이름을
map_options
로 지정합니다. - 리소스 유형으로 메뉴를 선택합니다.
- 확인을 클릭합니다.
- 코드 탭에서 새 파일의 코드를 다음 코드로 바꿔 지도 메뉴 옵션을 만듭니다. '없음' '없음'으로 인해 지도 유형이 생략되었습니다. 지도가 전혀 없을 수 있습니다. 이 단계에서 오류가 발생하지만 다음 단계에서 해결할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/normal_map"
android:title="@string/normal_map"
app:showAsAction="never" />
<item
android:id="@+id/hybrid_map"
android:title="@string/hybrid_map"
app:showAsAction="never" />
<item
android:id="@+id/satellite_map"
android:title="@string/satellite_map"
app:showAsAction="never" />
<item
android:id="@+id/terrain_map"
android:title="@string/terrain_map"
app:showAsAction="never" />
</menu>
strings.xml
에서 오류를 해결하기 위해title
속성의 리소스를 추가합니다.
<resources>
...
<string name="normal_map">Normal Map</string>
<string name="hybrid_map">Hybrid Map</string>
<string name="satellite_map">Satellite Map</string>
<string name="terrain_map">Terrain Map</string>
<string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
<string name="dropped_pin">Dropped Pin</string>
<string name="poi">poi</string>
</resources>
MapsActivity
에서onCreateOptionsMenu()
메서드를 재정의하고map_options
리소스 파일에서 메뉴를 확장합니다.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.map_options, menu)
return true
}
MapsActivity.kt
에서onOptionsItemSelected()
메서드를 재정의합니다. 사용자의 선택이 반영되도록 지도 유형 상수를 사용하여 지도 유형을 변경합니다.
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
// Change the map type based on the user's selection.
R.id.normal_map -> {
map.mapType = GoogleMap.MAP_TYPE_NORMAL
true
}
R.id.hybrid_map -> {
map.mapType = GoogleMap.MAP_TYPE_HYBRID
true
}
R.id.satellite_map -> {
map.mapType = GoogleMap.MAP_TYPE_SATELLITE
true
}
R.id.terrain_map -> {
map.mapType = GoogleMap.MAP_TYPE_TERRAIN
true
}
else -> super.onOptionsItemSelected(item)
}
- 앱을 실행합니다.
- 지도 유형을 변경하려면 아이콘을 클릭합니다. 모드별로 지도 모양이 어떻게 변하는지 확인하세요.
5. 작업: 마커 추가하기
기본적으로 onMapReady()
콜백에는 Google 지도가 만들어진 오스트레일리아 시드니에 마커를 배치하는 코드가 포함됩니다. 또한 기본 콜백은 지도를 시드니로 이동하도록 애니메이션을 적용합니다.
이 작업에서는 지도의 카메라를 집으로 이동하고 지정한 수준으로 확대/축소한 후 마커를 배치합니다.
1단계: 집을 확대/축소하고 마커 추가하기
MapsActivity.kt
파일에서onMapReady()
메서드를 찾습니다. 시드니에 마커를 배치하고 카메라를 이동하는 코드를 삭제합니다. 이제 메서드는 다음과 같이 표시됩니다.
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
}
- 이 안내에 따라 집의 위도와 경도를 확인하세요.
- 위도 값과 경도 값을 생성하고 부동 소수점 값을 입력합니다.
val latitude = 37.422160
val longitude = -122.084270
homeLatLng
라는 새LatLng
객체를 만듭니다.homeLatLng
객체에서 방금 만든 값을 전달합니다.
val homeLatLng = LatLng(latitude, longitude)
- 지도에서 얼마나 확대하고 싶은지에 관한
val
를 만듭니다. 확대/축소 수준 15f를 사용합니다.
val zoomLevel = 15f
확대/축소 수준은 지도에서 얼마나 확대된 정도를 제어합니다. 다음 목록을 통해 각 확대/축소 수준에서 표시되는 세부정보 수준을 알 수 있습니다.
1
: 전 세계5
: 대륙10
: 도시15
: 도로20
: 건물
map
객체에서moveCamera()
함수를 호출하여 카메라를homeLatLng
로 이동하고CameraUpdateFactory.newLatLngZoom()
를 사용하여CameraUpdate
객체를 전달합니다.homeLatLng
객체와zoomLevel
를 전달합니다.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
homeLatLng
의 지도에 마커를 추가합니다.
map.addMarker(MarkerOptions().position(homeLatLng))
최종 메서드는 다음과 같습니다.
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
//These coordinates represent the latitude and longitude of the Googleplex.
val latitude = 37.422160
val longitude = -122.084270
val zoomLevel = 15f
val homeLatLng = LatLng(latitude, longitude)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
map.addMarker(MarkerOptions().position(homeLatLng))
}
- 앱을 실행합니다. 지도가 집으로 이동하고, 원하는 수준으로 확대/축소하고, 집에 마커를 배치합니다.
2단계: 사용자가 긴 클릭으로 마커를 추가할 수 있도록 허용하기
이 단계에서는 사용자가 지도에서 위치를 길게 터치할 때 마커를 추가합니다.
MapsActivity
에GoogleMap
를 인수로 사용하는setMapLongClick()
라는 메서드 스텁을 만듭니다.- 지도 객체에
setOnMapLongClickListener
리스너를 연결합니다.
private fun setMapLongClick(map:GoogleMap) {
map.setOnMapLongClickListener { }
}
setOnMapLongClickListener()
에서addMarker()
메서드를 호출합니다. 전달된LatLng
로 설정된 위치를 사용하여 새MarkerOptions
객체를 전달합니다.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
onMapReady()
메서드 끝에서map
를 사용하여setMapLongClick()
를 호출합니다.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapLongClick(map)
}
- 앱을 실행합니다.
- 지도를 길게 터치하여 원하는 위치에 마커를 배치합니다.
- 마커를 탭하면 화면 중앙에 배치됩니다.
3단계: 마커에 대한 정보 창 추가
이 단계에서는 마커를 탭할 때 마커의 좌표를 표시하는 InfoWindow
를 추가합니다.
setMapLongClick()setOnMapLongClickListener()
에서snippet
의val
를 만듭니다. 스니펫은 제목 뒤에 표시되는 추가 텍스트입니다. 스니펫은 마커의 위도와 경도를 표시합니다.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
)
}
}
addMarker()
에서R.string.
dropped_pin
문자열 리소스를 사용하여 마커의title
를 고정된 핀으로 설정합니다.- 마커의
snippet
를snippet
로 설정합니다.
완성된 함수는 다음과 같습니다.
private fun setMapLongClick(map: GoogleMap) {
map.setOnMapLongClickListener { latLng ->
// A Snippet is Additional text that's displayed below the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
)
}
}
- 앱을 실행합니다.
- 위치 마커를 배치하려면 지도를 길게 터치합니다.
- 마커를 탭하여 정보 창을 표시합니다.
4단계: 관심 장소 리스너 추가
기본적으로 관심 장소 (POI)는 해당 아이콘과 함께 지도에 표시됩니다. 관심 장소에는 공원, 학교, 정부 건물 등이 포함됩니다. 지도 유형을 normal
로 설정하면 비즈니스 관심 장소도 지도에 표시됩니다. 비즈니스 관심 장소는 상점, 음식점, 호텔 등의 비즈니스를 나타냅니다.
이 단계에서는 GoogleMap.OnPoiClickListener
를 지도에 추가합니다. 이 클릭 리스너는 사용자가 관심 장소를 클릭하는 즉시 지도에 마커를 배치합니다. 클릭 리스너는 관심 장소 이름이 포함된 정보 창도 표시합니다.
MapsActivity
에GoogleMap
를 인수로 사용하는setPoiClick()
라는 메서드 스텁을 만듭니다.setPoiClick()
메서드에서 전달된GoogleMap
에OnPoiClickListener
를 설정합니다.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
}
}
setOnPoiClickListener()
에서 마커의val poiMarker
를 만듭니다 .MarkerOptions
와 함께map.addMarker()
를 사용하여 마커에 설정하고title
을 관심 장소의 이름으로 설정합니다.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
}
}
setOnPoiClickListener()
함수에서poiMarker
의showInfoWindow()
를 호출하여 정보 창을 즉시 표시합니다.
poiMarker.showInfoWindow()
setPoiClick()
함수의 최종 코드는 다음과 같습니다.
private fun setPoiClick(map: GoogleMap) {
map.setOnPoiClickListener { poi ->
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
poiMarker.showInfoWindow()
}
}
onMapReady()
끝에서setPoiClick()
를 호출하고map
를 전달합니다.
override fun onMapReady(googleMap: GoogleMap) {
...
setPoiClick(map)
}
- 앱을 실행하고 공원이나 커피숍과 같은 관심 장소를 찾습니다.
- 관심 장소를 탭하여 마커를 배치하고 정보 창에 관심 장소의 이름을 표시합니다.
6. 작업: 지도 스타일 지정
다양한 방법으로 Google 지도를 맞춤설정하여 나만의 지도를 만들 수 있습니다.
다른 프래그먼트를 맞춤설정하는 것처럼 사용 가능한 XML 속성을 사용하여 MapFragment
객체를 맞춤설정할 수 있습니다. 그러나 이 단계에서는 GoogleMap
객체의 메서드를 사용하여 MapFragment
콘텐츠의 디자인과 분위기를 맞춤설정합니다.
지도에 맞춤설정된 스타일을 만들려면 지도의 지형지물이 표시되는 방식을 지정하는 JSON 파일을 생성합니다. 이 JSON 파일을 수동으로 만들 필요가 없습니다. Google에서는 지도의 스타일을 시각적으로 지정한 후 JSON을 생성해 주는 지도 플랫폼 스타일 지정 마법사를 제공합니다. 이 작업에서는 레트로 테마로 지도의 스타일을 지정합니다. 즉, 지도는 빈티지 색상을 사용하고 색상이 지정된 도로를 추가합니다.
1단계: 지도의 스타일 만들기
- 브라우저에서 https://mapstyle.withgoogle.com/으로 이동합니다.
- 스타일 만들기를 선택합니다.
- Retro를 선택합니다.
- 옵션 더보기를 클릭합니다.
- 도로를 선택합니다. 채우기.
- 도로의 색상을 원하는 색상 (예: 분홍색)으로 변경합니다.
- 마침을 클릭합니다.
- 결과 대화상자에서 JSON 코드를 복사하고 원하는 경우 다음 단계에서 사용할 수 있도록 일반 텍스트 메모에 보관합니다.
2단계: 지도에 스타일 추가
- Android 스튜디오의
res
디렉터리에서 리소스 디렉터리를 만들고 이름을raw
로 지정합니다. JSON 코드와 같은raw
디렉터리 리소스를 사용합니다. res/raw
에map_style.json
라는 파일을 만듭니다.- 저장된 JSON 코드를 새 리소스 파일에 붙여넣습니다.
MapsActivity
에서onCreate()
메서드 위에TAG
클래스 변수를 만듭니다. 로깅 목적으로 사용됩니다.
private val TAG = MapsActivity::class.java.simpleName
- 또한
MapsActivity
에서GoogleMap
를 사용하는setMapStyle()
함수를 만듭니다. setMapStyle()
에서try{}
블록을 추가합니다.try{}
블록에서 성공적인 스타일 지정을 위한val success
를 만듭니다. 다음 catch 블록을 추가합니다.try{}
블록에서 JSON 스타일을 지도에 설정하고GoogleMap
객체에서setMapStyle()
를 호출합니다. JSON 파일을 로드하는MapStyleOptions
객체를 전달합니다.- 결과를
success
에 할당합니다.setMapStyle()
메서드는 스타일 지정 파일을 파싱하고 스타일 설정의 성공 상태를 나타내는 불리언을 반환합니다.
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
}
}
- false인
success
의 if 문을 추가합니다. 스타일 지정에 실패하면 파싱에 실패한 로그를 출력합니다.
private fun setMapStyle(map: GoogleMap) {
try {
...
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
}
}
catch{}
블록을 추가하여 스타일 파일이 누락된 상황을 처리합니다.catch
블록에서 파일을 로드할 수 없는 경우Resources.NotFoundException
이 발생합니다.
private fun setMapStyle(map: GoogleMap) {
try {
...
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
완성된 메서드는 다음 코드 스니펫과 같습니다.
private fun setMapStyle(map: GoogleMap) {
try {
// Customize the styling of the base map using a JSON object defined
// in a raw resource file.
val success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this,
R.raw.map_style
)
)
if (!success) {
Log.e(TAG, "Style parsing failed.")
}
} catch (e: Resources.NotFoundException) {
Log.e(TAG, "Can't find style. Error: ", e)
}
}
- 마지막으로
GoogleMap
객체를 전달하는onMapReady()
메서드에서setMapStyle()
메서드를 호출합니다.
override fun onMapReady(googleMap: GoogleMap) {
...
setMapStyle(map)
}
- 앱을 실행합니다.
- 지도를
normal
모드로 설정하면 새로운 스타일이 레트로 테마 설정과 선택한 색상의 도로로 표시됩니다.
3단계: 마커 스타일 지정
지도 마커의 스타일을 지정하여 지도를 더욱 맞춤설정할 수 있습니다. 이 단계에서는 기본 빨간색 마커를 더 멋진 것으로 변경합니다.
onMapLongClick()
메서드에서 생성자의MarkerOptions()
에 다음 코드 줄을 추가하여 기본 마커를 사용하지만 색상은 파란색으로 변경합니다.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
이제 onMapLongClickListener()
는 다음과 같이 표시됩니다.
map.setOnMapLongClickListener { latLng ->
// A snippet is additional text that's displayed after the title.
val snippet = String.format(
Locale.getDefault(),
"Lat: %1$.5f, Long: %2$.5f",
latLng.latitude,
latLng.longitude
)
map.addMarker(
MarkerOptions()
.position(latLng)
.title(getString(R.string.dropped_pin))
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
)
}
- 앱을 실행합니다. 이제 길게 클릭하면 나타나는 마커가 파란색 음영으로 표시됩니다.
onPoiClick()
메서드에 스타일을 추가하지 않았으므로 관심 장소 마커는 여전히 빨간색입니다.
7. 작업: 오버레이 추가
Google 지도를 맞춤설정하는 한 가지 방법은 지도 위에 그림을 그리는 것입니다. 이 기술은 인기 있는 낚시터와 같이 특정 유형의 위치를 강조표시하려는 경우에 유용합니다.
- 도형: 지도에 다중선, 다각형, 원을 추가할 수 있습니다.
GroundOverlay
객체: 지면 오버레이는 지도에 고정된 이미지입니다. 마커와 달리 지면 오버레이는 화면이 아닌 지표면을 향합니다. 지도를 회전하거나 기울이거나 확대/축소하면 이미지의 방향이 바뀝니다. 지면 오버레이는 단일 이미지를 지도의 한 영역에 고정하려는 경우에 유용합니다.
단계: 지면 오버레이 추가
이 작업에서는 Android 모양의 지면 오버레이를 홈 위치에 추가합니다.
- 이 Android 이미지를 다운로드하여
res/drawable
폴더에 저장합니다. 파일 이름이android.png
이어야 합니다.
onMapReady()
에서 카메라를 홈 위치로 이동하도록 호출한 후GroundOverlayOptions
객체를 만듭니다.- 객체를
androidOverlay
라는 변수에 할당합니다.
val androidOverlay = GroundOverlayOptions()
BitmapDescriptorFactory.fromResource()
메서드를 사용하여 다운로드한 이미지 리소스에서BitmapDescriptor
객체를 만듭니다.- 결과
BitmapDescriptor
객체를GroundOverlayOptions
객체의image()
메서드에 전달합니다.
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
- 원하는 오버레이의 너비(미터 단위)에 관한
float overlaySize
를 만듭니다. 이 예에서는100f
너비가 적합합니다.
position()
메서드를 호출하여 GroundOverlayOptions
객체의 position
속성을 설정하고 homeLatLng
객체와 overlaySize
를 전달합니다.
val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.android))
.position(homeLatLng, overlaySize)
GoogleMap
객체에서addGroundOverlay()
를 호출하고GroundOverlayOptions
객체를 전달합니다.
map.addGroundOverlay(androidOverlay)
- 앱을 실행합니다.
- Android 이미지를 오버레이로 보려면
zoomLevel
값을 18f로 변경합니다.
8. 작업: 위치 추적 사용 설정
사용자는 종종 Google 지도를 사용하여 현재 위치를 확인합니다. 지도에 기기 위치를 표시하려면 위치 데이터 레이어를 사용하면 됩니다.
위치 데이터 레이어는 지도에 내 위치 아이콘을 추가합니다.
사용자가 버튼을 탭하면 기기의 위치가 지도 중앙에 배치됩니다. 기기가 움직이지 않으면 위치는 파란색 점으로, 기기가 움직이는 경우 파란색 V자형으로 표시됩니다.
이 작업에서는 위치 데이터 레이어를 사용 설정합니다.
단계: 위치 정보 액세스 권한 요청
Google 지도에서 위치 추적을 사용하려면 한 줄의 코드가 필요합니다. 그러나 런타임 권한 모델을 사용하여 사용자가 위치 정보 액세스 권한을 부여했는지 확인해야 합니다.
이 단계에서는 위치 정보 액세스 권한을 요청하고 위치 추적을 사용 설정합니다.
AndroidManifest.xml
파일에FINE_LOCATION
권한이 이미 있는지 확인합니다. Google 지도 템플릿을 선택할 때 Android 스튜디오가 이 권한을 삽입했습니다.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
MapsActivity
에서REQUEST_LOCATION_PERMISSION
클래스 변수를 만듭니다.
private val REQUEST_LOCATION_PERMISSION = 1
- 권한이 부여되었는지 확인하려면
MapsActivity
에서isPermissionGranted()
라는 메서드를 만듭니다. 이 메서드에서 사용자가 권한을 부여했는지 확인합니다.
private fun isPermissionGranted() : Boolean {
return ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
- 앱에서 위치 추적을 사용 설정하려면
MapsActivity
에서 인수를 사용하지 않고 아무것도 반환하지 않는enableMyLocation()
라는 메서드를 만듭니다. 내부에서ACCESS_FINE_LOCATION
권한을 확인합니다. 권한이 부여되면 위치 레이어를 사용 설정합니다. 권한이 없다면 권한을 요청합니다.
private fun enableMyLocation() {
if (isPermissionGranted()) {
map.isMyLocationEnabled = true
}
else {
ActivityCompat.requestPermissions(
this,
arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
}
onMapReady()
콜백에서enableMyLocation()
를 호출하여 위치 레이어를 사용 설정합니다.
override fun onMapReady(googleMap: GoogleMap) {
...
enableMyLocation()
}
onRequestPermissionsResult()
메서드를 재정의합니다.requestCode
가REQUEST_LOCATION_PERMISSION
와 같은지 확인합니다. 설정된 경우 권한이 부여되었음을 의미합니다. 권한이 부여되면grantResults
배열의 첫 번째 슬롯에PackageManager.PERMISSION_GRANTED
가 포함되어 있는지도 확인합니다. true이면enableMyLocation()
를 호출합니다.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
enableMyLocation()
}
}
}
- 앱을 실행합니다. 기기 위치에 대한 액세스를 요청하는 대화상자가 있어야 합니다. 권한을 허용하세요.
이제 지도에 기기의 현재 위치가 파란색 점으로 표시됩니다. 위치 버튼이 있습니다. 지도를 내 위치에서 멀리 이동한 다음 이 버튼을 클릭하면 기기의 위치가 지도의 중심에 다시 맞춰집니다.
9. 솔루션 코드
완료된 Codelab의 코드를 다운로드합니다.
$ git clone https://github.com/googlecodelabs/android-kotlin-geo-maps
또는 ZIP 파일로 저장소를 다운로드한 다음 압축을 풀고 Android 스튜디오에서 열어도 됩니다.
10. 요약
축하합니다. Android Kotlin 앱에 Google 지도를 추가하고 스타일을 지정했습니다.
11. 자세히 알아보기
Android 개발자 문서:
참조 문서
12. 다음 Codelab
이 과정의 다른 Codelab 링크는 Kotlin 기반 Android 고급 Codelab 방문 페이지를 참고하세요.