Android 09.1 고급: Google 지도

1. 환영합니다

이 Codelab은 Google Developers 교육팀에서 개발한 고급 Android 개발 교육 과정의 일부입니다. Codelab을 순서대로 살펴보면 이 과정을 최대한 활용할 수 있습니다.

교육 과정에 관한 전체 세부정보는 고급 Android 개발 개요를 참고하세요.

소개

Google 지도로 앱을 빌드하면 위성 이미지, 강력한 UI 컨트롤, 위치 추적, 위치 마커와 같은 기능을 앱에 추가할 수 있습니다. 유명한 낚시 또는 등산 구역의 위치 등 자체 데이터 세트의 정보를 표시하여 표준 Google 지도에 가치를 더할 수 있습니다. Pokémon Go처럼 현실 세계와 연결된 게임을 만들 수도 있습니다.

이 실습에서는 Wander라는 Google 지도 앱을 만듭니다.

기본 요건

다음을 잘 알고 있어야 합니다.

  • Google 지도의 기본 기능
  • 런타임 권한
  • Android 스튜디오에서 앱 만들기, 빌드, 실행하기
  • build.gradle 파일에 외부 라이브러리를 포함합니다.

학습할 내용

  • 앱에 Google 지도를 통합합니다.
  • 다양한 지도 유형을 표시합니다.
  • Google 지도의 스타일을 지정합니다.
  • 지도에 마커를 추가합니다.
  • 사용자가 관심 장소 (POI)에 마커를 배치할 수 있도록 합니다.
  • 위치 추적을 사용 설정합니다.
  • Google 스트리트 뷰를 사용합니다.

실습할 내용

  • Google API 콘솔에서 API 키를 가져와서 앱에 등록합니다.
  • Google 지도가 삽입된 Wander 앱을 만듭니다.
  • 마커, 스타일 지정, 위치 추적과 같은 맞춤 기능을 앱에 추가합니다.
  • 앱에서 위치 추적 및 스트리트 뷰를 사용 설정합니다.

2. 앱 개요

이 실습에서는 스타일이 지정된 Google 지도인 Wander 앱을 만듭니다. Wander 앱을 사용하면 위치에 마커를 배치하고 실시간으로 내 위치를 확인하며 스트리트 뷰 파노라마를 볼 수 있습니다.

스타일 Google 지도

Android 앱의 Google 스트리트 뷰

3. 작업 1. 프로젝트 설정 및 API 키 가져오기

Places API와 마찬가지로 Google 지도 API에도 API 키가 필요합니다. API 키를 얻으려면 Google API 콘솔에 프로젝트를 등록하세요. API 키는 앱을 작성자와 연결하는 디지털 인증서에 연결됩니다. 디지털 인증서 사용 및 앱 서명에 관한 자세한 내용은 앱 서명을 참고하세요.

이 실습에서는 디버그 인증서에 API 키를 사용합니다. 디버그 인증서는 디버그 빌드 서명에 설명된 대로, 의도적으로 안전하지 않습니다. Google Maps API를 사용하여 게시된 Android 앱에는 두 번째 API 키, 즉 출시 인증서용 키가 필요합니다. 출시 인증서 가져오기에 대한 자세한 내용은 API 키 가져오기를 참고하세요.

Android 스튜디오에는 유용한 템플릿 코드를 생성하는 Google Maps Activity 템플릿이 포함되어 있습니다. 템플릿 코드에는 API 키 획득을 간소화하는 링크가 포함된 google_maps_api.xml 파일이 포함되어 있습니다.

1.1 지도 템플릿으로 Wander 프로젝트 만들기

  1. 새 Android 스튜디오 프로젝트를 만듭니다.
  2. 새 앱의 이름을 'Wander'로 지정합니다. Add an Activity 페이지가 표시될 때까지 기본값을 수락합니다.
  3. Google Maps Activity 템플릿을 선택합니다.
  4. 기본 Activity NameLayout Name은 그대로 둡니다.
  5. 제목을 'Wander'로 변경합니다. 마침을 클릭합니다.

Android 스튜디오는 여러 지도 관련 추가 파일을 만듭니다.

google_maps_api**.xml**

이 구성 파일을 사용하여 API 키를 보관합니다. 이 템플릿은 디버그용과 출시용, 이렇게 두 개의 google_maps_api.xml 파일을 생성합니다. 디버그 인증서의 API 키 파일은 src/debug/res/values에 있습니다. 출시 인증서의 API 키 파일은 src/release/res/values에 있습니다. 이 실습에서는 디버그 인증서만 사용합니다.

activity_maps.xml

이 레이아웃 파일에는 전체 화면을 채우는 단일 프래그먼트가 포함되어 있습니다. SupportMapFragment 클래스는 Fragment 클래스의 서브클래스입니다. 추가 속성과 함께 ViewGroup에서 <fragment> 태그를 사용하여 레이아웃 파일에 SupportMapFragment를 포함할 수 있습니다.

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java

MapsActivity.java 파일은 SupportMapFragment 클래스를 인스턴스화하고 클래스의 getMapAsync() 메서드를 사용하여 Google 지도를 준비합니다. SupportMapFragment가 포함된 활동은 OnMapReadyCallback 인터페이스와 인터페이스의 onMapReady() 메서드를 구현해야 합니다. getMapAsync() 메서드는 지도가 로드되었음을 나타내는 GoogleMap 객체를 반환합니다.

1.2 API 키 가져오기

  1. google_maps_api.xml 파일의 디버그 버전을 엽니다.

파일에 긴 URL의 댓글이 포함되어 있습니다. URL의 매개변수에는 앱에 대한 특정 정보가 포함됩니다.

  1. URL을 복사하여 브라우저에 붙여넣습니다.
  2. 안내에 따라 Google API 콘솔에서 프로젝트를 만듭니다. 제공된 URL의 매개변수 때문에 API 콘솔은 자동으로 Google Maps Android API를 사용 설정합니다.
  3. API 키를 만들고 키 제한을 클릭하여 키 사용을 Android 앱으로 제한합니다. 생성된 API 키는 AIza로 시작해야 합니다.
  4. google_maps_api.xml 파일에서 YOUR_KEY_HERE라고 표시된 google_maps_key 문자열에 키를 붙여넣습니다.
  5. 앱을 실행합니다. 활동에 삽입된 지도가 있고 오스트레일리아 시드니에 마커가 설정되어 있습니다. 시드니 마커는 템플릿의 일부이며, 나중에 변경할 수 있습니다.

4. 작업 2. 지도 유형 및 마커 추가

Google 지도에는 일반, 하이브리드, 위성, 지형 및 '없음' 등 여러 지도 유형이 포함됩니다. 이 작업에서는 사용자가 지도 유형을 변경할 수 있는 옵션 메뉴가 있는 앱 바를 추가합니다. 지도의 시작 위치를 자신의 집 위치로 옮깁니다. 그런 다음 지도에서 단일 위치를 나타내고 라벨을 포함할 수 있는 마커 지원을 추가합니다.

2.1 지도 유형 추가하기

사용자가 원하는 지도 유형은 필요한 정보의 종류에 따라 다릅니다. 자동차에서 내비게이션을 위해 지도를 사용할 때는 거리 이름을 명확하게 보는 것이 좋습니다. 하이킹을 할 때는 아마 산 정상에 오르기 위해 등반해야 하는 양이 더 중요할 것입니다. 이 단계에서는 사용자가 지도 유형을 변경할 수 있는 옵션 메뉴가 있는 앱 바를 추가합니다.

  1. 새 메뉴 XML 파일을 만들려면 res 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 New > Android 리소스 파일.
  2. 대화상자에서 파일 이름을 map_options로 지정합니다. 리소스 유형으로 메뉴를 선택합니다. 확인을 클릭합니다.
  3. 새 파일의 코드를 다음 코드로 바꿔 지도 옵션을 만듭니다. '없음' '없음'이므로 지도 유형이 생략됩니다. 지도가 전혀 없을 수 있습니다.
<?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>
  1. title 속성의 문자열 리소스를 만듭니다.
  2. MapsActivity 파일에서 FragmentActivity 클래스를 확장하는 대신 AppCompatActivity 클래스를 확장하도록 클래스를 변경합니다. AppCompatActivity를 사용하면 앱 바가 표시되므로 메뉴가 표시됩니다.
  3. MapsActivity에서 onCreateOptionsMenu() 메서드를 재정의하고 map_options 파일을 확장합니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.map_options, menu);
   return true;
}
  1. 지도 유형을 변경하려면 GoogleMap 객체의 setMapType() 메서드를 사용하여 지도 유형 상수 중 하나를 전달합니다.

onOptionsItemSelected() 메서드를 재정의합니다. 다음 코드를 붙여넣어 사용자가 메뉴 옵션 중 하나를 선택할 때 지도 유형을 변경합니다.

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Change the map type based on the user's selection.
       switch (item.getItemId()) {
           case R.id.normal_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               return true;
           case R.id.hybrid_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
               return true;
           case R.id.satellite_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
               return true;
           case R.id.terrain_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }
  1. 앱을 실행합니다. 앱 바의 메뉴를 사용하여 지도 유형을 변경합니다. 지도의 모양이 어떻게 바뀌는지 확인합니다.

2.2 기본 지도 위치 이동하기

기본적으로 onMapReady() 콜백에는 Google 지도가 만들어진 오스트레일리아 시드니에 마커를 배치하는 코드가 포함됩니다. 또한 기본 콜백은 지도를 시드니로 이동하도록 애니메이션을 적용합니다. 이 단계에서는 마커를 배치하지 않고 지도에서 집 위치를 이동한 다음 지정한 수준으로 확대/축소합니다.

  1. onMapReady() 메서드에서 시드니에 마커를 배치하고 카메라를 이동하는 코드를 삭제합니다.
  2. 브라우저에서 www.google.com/maps로 이동하여 집을 찾습니다.
  3. 위치를 마우스 오른쪽 버튼으로 클릭하고 이곳이 궁금한가요?를 선택합니다.

화면 하단에 위도와 경도를 포함한 위치 정보가 포함된 작은 창이 표시됩니다.

  1. home라는 새 LatLng 객체를 만듭니다. LatLng 객체에서 브라우저의 Google 지도에서 찾은 좌표를 사용합니다.
  2. zoom라는 float 변수를 만들고 이 변수를 원하는 초기 확대/축소 수준으로 설정합니다. 다음 목록을 통해 각 확대/축소 수준에서 표시되는 세부정보 수준을 알 수 있습니다.
  • 1: 전 세계
  • 5: 대륙
  • 10: 도시
  • 15: 도로
  • 20: 건물
  1. CameraUpdateFactory.newLatLngZoom()를 사용하여 CameraUpdate 객체를 만들고 LatLng 객체와 zoom 변수를 전달합니다. GoogleMap 객체에서 moveCamera()를 호출하고 새 CameraUpdate 객체를 전달하여 카메라를 화면 이동 및 확대/축소합니다.
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(home, zoom));
  1. 앱을 실행합니다. 지도가 집으로 이동하고 원하는 수준으로 확대됩니다.

2.3 지도 마커 추가하기

Google 지도는 Marker 클래스를 사용하여 만드는 마커를 사용하여 위치를 지정할 수 있습니다. 기본 마커는 표준 Google 지도 아이콘(Google 지도 마커)을 사용합니다.

마커를 확장하여 정보 창에 상황 정보를 표시할 수 있습니다.

이 단계에서는 사용자가 지도에서 위치를 길게 터치할 때 마커를 추가합니다. 그런 다음 마커를 탭하면 마커의 좌표를 표시하는 InfoWindow를 추가합니다.

핀 고정에 대한 정보 창

  1. MapsActivityfinal GoogleMap를 인수로 사용하고 void를 반환하는 setMapLongClick()라는 메서드 스텁을 만듭니다.
private void setMapLongClick(final GoogleMap map) {}
  1. GoogleMap 객체의 setOnMapLongClickListener() 메서드를 사용하여 사용자가 길게 터치하는 위치에 마커를 배치합니다. onMapLongClick() 메서드를 재정의하는 OnMapLongClickListener의 새 인스턴스를 전달합니다. 수신 인수는 사용자가 누른 위치의 좌표가 포함된 LatLng 객체입니다.
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. onMapLongClick() 내에서 addMarker() 메서드를 호출합니다. 위치를 전달된 LatLng로 설정하여 새 MarkerOptions 객체를 전달합니다.
map.addMarker(new MarkerOptions().position(latLng));
  1. onMapReady() 메서드 끝에서 setMapLongClick()를 호출합니다. mMap를 전달합니다.
  2. 앱을 실행합니다. 지도를 길게 터치하여 원하는 위치에 마커를 배치합니다.
  3. 마커를 탭하면 화면 중앙에 배치됩니다.

탐색 버튼은 화면 왼쪽 하단에 표시되므로 사용자는 Google 지도 앱을 사용하여 표시된 위치로 이동할 수 있습니다.

마커에 대한 정보 창을 추가하는 방법:

  1. MarkerOptions 객체에서 title 필드와 snippet 필드를 설정합니다.
  2. onMapLongClick()에서 title 입력란을 '고정된 핀'으로 설정합니다. snippet 필드를 addMarker() 메서드 내의 위치 좌표로 설정합니다.
map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
   @Override
   public void onMapLongClick(LatLng latLng) {
       String snippet = String.format(Locale.getDefault(),
               "Lat: %1$.5f, Long: %2$.5f",
               latLng.latitude,
               latLng.longitude);

       map.addMarker(new MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet));
   }
});
  1. 앱을 실행합니다. 위치 마커를 배치하려면 지도를 길게 터치합니다. 마커를 탭하여 정보 창을 표시합니다.

2.4 관심 장소 리스너 추가

기본적으로 관심 장소 (POI)는 해당 아이콘과 함께 지도에 표시됩니다. 관심 장소에는 공원, 학교, 정부 건물 등이 포함됩니다. 지도 유형을 normal로 설정하면 비즈니스 관심 장소도 지도에 표시됩니다. 비즈니스 관심 장소는 상점, 음식점, 호텔 등의 비즈니스를 나타냅니다.

이 단계에서는 GoogleMap.OnPoiClickListener를 지도에 추가합니다. 이 클릭 리스너는 터치 및 길게 누릅니다. 클릭 리스너는 관심 장소 이름이 포함된 정보 창도 표시합니다.

관심 장소 마커

  1. MapsActivityfinal GoogleMap를 인수로 사용하고 void를 반환하는 setPoiClick()라는 메서드 스텁을 만듭니다.
private void setPoiClick(final GoogleMap map) {}
  1. setPoiClick() 메서드에서 전달된 GoogleMapOnPoiClickListener를 설정합니다.
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. onPoiClick() 메서드에서 관심 장소 위치에 마커를 배치합니다. 제목을 관심 장소의 이름으로 설정합니다. 결과를 poiMarker라는 변수에 저장합니다.
public void onPoiClick(PointOfInterest poi) {
   Marker poiMarker = mMap.addMarker(new MarkerOptions()
       .position(poi.latLng)
       .title(poi.name);
}
  1. 정보 창을 즉시 표시하려면 poiMarker에서 showInfoWindow()를 호출합니다.
poiMarker.showInfoWindow();
  1. onMapReady()가 끝날 때 setPoiClick()를 호출합니다. mMap를 전달합니다.
  2. 앱을 실행하고 공원과 같은 관심 장소를 찾습니다. 관심 장소를 탭하여 마커를 배치하고 정보 창에 관심 장소의 이름을 표시합니다.

5. 작업 3. 지도 스타일 지정

다양한 방법으로 Google 지도를 맞춤설정하여 나만의 지도를 만들 수 있습니다.

다른 프래그먼트를 맞춤설정하는 것처럼 사용 가능한 XML 속성을 사용하여 MapFragment 객체를 맞춤설정할 수 있습니다. 그러나 이 단계에서는 GoogleMap 객체의 메서드를 사용하여 MapFragment 콘텐츠의 디자인과 분위기를 맞춤설정합니다. 온라인 스타일 지정 마법사를 사용하여 지도에 스타일을 추가하고 마커를 맞춤설정할 수 있습니다. 또한 지도에 따라 확장 및 회전되는 GroundOverlay를 집 위치에 추가합니다.

3.1 지도에 스타일 추가

지도에 맞춤설정된 스타일을 만들려면 지도의 지형지물이 표시되는 방식을 지정하는 JSON 파일을 생성합니다. 이 JSON 파일을 수동으로 만들 필요가 없습니다. Google에서 제공하는 스타일 지정 마법사를 사용하면 시각적으로 지도의 스타일을 지정한 후 JSON을 생성할 수 있습니다. 이 실습에서는 '야간 모드'를 위해 지도의 스타일을 지정합니다. 은 지도가 어두운 색상과 낮은 대비를 사용하여 야간에 사용된다는 것을 의미합니다.

  1. 브라우저에서 https://mapstyle.withgoogle.com/으로 이동합니다.
  2. 스타일 만들기를 선택합니다.
  3. 야간 테마를 선택합니다.
  4. 메뉴 하단의 옵션 더보기를 클릭합니다.
  5. 지형지물 유형 목록 하단에서 물 > 물 >을 선택합니다. 채우기. 물의 색을 진한 파란색으로 변경합니다 (예: #160064).
  6. 마침을 클릭합니다. 표시되는 팝업 창에서 JSON 코드를 복사합니다.
  7. Android 스튜디오에서 res 디렉터리에 raw라는 리소스 디렉터리를 만듭니다. res/rawmap_style.json라는 파일을 만듭니다.
  8. JSON 코드를 새 리소스 파일에 붙여넣습니다.
  9. 지도에 JSON 스타일을 설정하려면 GoogleMap 객체에서 setMapStyle()를 호출합니다. JSON 파일을 로드하는 MapStyleOptions 객체를 전달합니다. setMapStyle() 메서드는 스타일 지정의 성공을 나타내는 불리언을 반환합니다. 파일을 로드할 수 없는 경우 메서드에서 Resources.NotFoundException이 발생합니다.

다음 코드를 onMapReady() 메서드에 복사하여 지도의 스타일을 지정합니다. 로그 구문에 TAG 문자열을 만들어야 할 수도 있습니다.

     try {
        // Customize the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
                   this, R.raw.map_style));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
     } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
     }
  1. 앱을 실행합니다. 지도가 normal 모드일 때 새 스타일이 표시되어야 합니다.

야간 모드 스타일의 Google 지도

3.2 마커 스타일 지정

지도 마커의 스타일을 지정하여 지도를 더욱 맞춤설정할 수 있습니다. 이 단계에서는 야간 모드 색 구성표와 일치하도록 기본 빨간색 마커를 변경합니다.

  1. onMapLongClick() 메서드에서 다음 코드 줄을 MarkerOptions() 생성자에 추가하여 기본 마커를 사용하지만 색상은 파란색으로 변경합니다.
.icon(BitmapDescriptorFactory.defaultMarker
       (BitmapDescriptorFactory.HUE_BLUE))
  1. 앱을 실행합니다. 이제 배치하는 마커가 파란색 음영으로 표시되며, 이는 앱의 야간 모드 테마와 더 일관됩니다.

onPoiClick() 메서드에 스타일을 추가하지 않았으므로 관심 장소 마커는 여전히 빨간색입니다.

3.3 오버레이 추가하기

Google 지도 위에 그림을 그리면 Google 지도를 맞춤설정할 수 있습니다. 이 기술은 인기 있는 낚시터와 같이 특정 유형의 위치를 강조표시하려는 경우에 유용합니다. 세 가지 유형의 오버레이가 지원됩니다.

  • 도형: 지도에 다중선, 다각형, 을 추가할 수 있습니다.
  • TileOverlay 객체: 타일 오버레이는 기본 지도 타일 위에 추가되는 이미지 집합을 정의합니다. 타일 오버레이는 지도에 광범위한 이미지를 추가하려는 경우에 유용합니다. 일반적인 타일 오버레이는 넓은 지리적 영역을 덮습니다.
  • GroundOverlay 객체: 지면 오버레이는 지도에 고정된 이미지입니다. 마커와 달리 지면 오버레이는 화면이 아닌 지표면을 향합니다. 지도를 회전하거나 기울이거나 확대/축소하면 이미지의 방향이 바뀝니다. 지면 오버레이는 단일 이미지를 지도의 한 영역에 고정하려는 경우에 유용합니다.

이 단계에서는 Android 모양의 지면 오버레이를 집 위치에 추가합니다.

  1. 이 Android 이미지를 다운로드하여 res/drawable 폴더에 저장합니다.
  2. onMapReady()에서 카메라를 홈 위치로 이동하는 호출 후 GroundOverlayOptions 객체를 만듭니다. 객체를 homeOverlay라는 변수에 할당합니다.
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. BitmapDescriptorFactory.fromResource() 메서드를 사용하여 위 이미지에서 BitmapDescriptor 객체를 만듭니다. 다음과 같이 GroundOverlayOptions 객체의 image() 메서드에 객체를 전달합니다.
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.android));
  1. position() 메서드를 호출하여 GroundOverlayOptions 객체의 position 속성을 설정합니다. home LatLng 객체와 원하는 오버레이의 너비(미터 단위)에 관한 float을 전달합니다. 이 예에서는 너비를 100m로 설정하는 것이 좋습니다.
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
     .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
       .position(home, 100);
  1. GoogleMap 객체에서 addGroundOverlay()를 호출합니다. GroundOverlayOptions 객체를 전달합니다.
mMap.addGroundOverlay(homeOverlay);
  1. 앱을 실행합니다. 집 위치를 확대하면 Android 이미지가 오버레이로 표시됩니다.

6. 작업 4. 위치 추적 및 스트리트 뷰 사용

사용자는 Google 지도를 사용하여 현재 위치를 확인하는 경우가 많으며, 개발자는 Location Services API를 사용하여 기기 위치를 가져올 수 있습니다. Location 데이터를 더 이상 사용하지 않고 지도에 기기 위치를 표시하려면 위치 데이터 레이어를 사용하세요.

위치 데이터 레이어는 지도의 오른쪽 상단에 내 위치 버튼을 추가합니다. 사용자가 버튼을 탭하면 기기의 위치가 지도 중앙에 배치됩니다. 기기가 움직이지 않으면 위치가 파란색 점으로, 기기가 움직이면 파란색 V자형으로 표시됩니다.

위치 추적 기능이 있는 스타일 Google 지도

특정 위치의 탐색 가능한 파노라마 사진인 Google 스트리트 뷰를 사용하여 위치에 대한 추가 정보를 제공할 수 있습니다.

이 작업에서는 사용자가 관심 장소 마커의 정보 창을 탭하면 지도가 스트리트 뷰 모드로 전환되도록 위치 데이터 레이어와 스트리트 뷰를 사용 설정합니다.

4.1 위치 추적 사용 설정

Google 지도에서 위치 추적을 사용하려면 한 줄의 코드가 필요합니다. 그러나 런타임 권한 모델을 사용하여 사용자가 위치 정보 액세스 권한을 부여했는지 확인해야 합니다.

이 단계에서는 위치 정보 액세스 권한을 요청하고 위치 추적을 사용 설정합니다.

  1. AndroidManifest.xml 파일에 FINE_LOCATION 권한이 이미 있는지 확인합니다. Google 지도 템플릿을 선택할 때 Android 스튜디오가 이 권한을 삽입했습니다.
  2. 앱에서 위치 추적을 사용 설정하려면 MapsActivity에서 인수를 사용하지 않고 아무것도 반환하지 않는 enableMyLocation()라는 메서드를 만듭니다.
  3. enableMyLocation() 메서드를 정의합니다. ACCESS_FINE_LOCATION 권한을 확인합니다. 권한이 부여되면 위치 레이어를 사용 설정합니다. 권한이 없는 경우에는 권한을 요청합니다.
private void enableMyLocation() {
   if (ContextCompat.checkSelfPermission(this,
           Manifest.permission.ACCESS_FINE_LOCATION)
           == PackageManager.PERMISSION_GRANTED) {
       mMap.setMyLocationEnabled(true);
   } else {
       ActivityCompat.requestPermissions(this, new String[]
                       {Manifest.permission.ACCESS_FINE_LOCATION},
               REQUEST_LOCATION_PERMISSION);
   }
}
  1. onMapReady() 콜백에서 enableMyLocation()를 호출하여 위치 레이어를 사용 설정합니다.
  2. onRequestPermissionsResult() 메서드를 재정의합니다. 권한이 부여되면 다음과 같이 enableMyLocation()를 호출합니다.
@Override
public void onRequestPermissionsResult(int requestCode,
       @NonNull String[] permissions,
       @NonNull int[] grantResults) {
   // Check if location permissions are granted and if so enable the
   // location data layer.
   switch (requestCode) {
       case REQUEST_LOCATION_PERMISSION:
           if (grantResults.length > 0
                   && grantResults[0]
                   == PackageManager.PERMISSION_GRANTED) {
               enableMyLocation();
               break;
           }
   }
}
  1. 앱을 실행합니다. 이제 오른쪽 상단에 기기의 현재 위치를 표시하는 내 위치 버튼이 포함됩니다.

4.2 스트리트 뷰 사용 설정

Google 지도에서는 지정된 경로를 따라 이동하기 위한 컨트롤이 있는 위치의 파노라마 뷰인 스트리트 뷰를 제공합니다. 스트리트 뷰는 전 세계를 대상으로 하지 않습니다.

이 단계에서는 사용자가 관심 장소의 정보 창을 탭할 때 활성화되는 스트리트 뷰 파노라마를 활성화합니다. 다음 두 가지 작업을 수행해야 합니다.

  1. 앱의 기능이 관심 장소 마커에서만 작동하기를 원하므로 관심 장소 마커를 다른 마커와 구별하세요. 이렇게 하면 사용자가 관심 장소 정보 창을 탭할 때 스트리트 뷰를 시작할 수 있지만 다른 유형의 마커를 탭할 때는 시작할 수 없습니다.

Marker 클래스에는 데이터를 연결할 수 있는 setTag() 메서드가 포함되어 있습니다. (데이터는 Object에서 확장된 모든 데이터일 수 있습니다.) 사용자가 관심 장소를 클릭할 때 생성되는 마커에 태그를 설정합니다.

  1. 사용자가 OnInfoWindowClickListener에서 태그된 정보 창을 탭하면 MapFragmentStreetViewPanoramaFragment로 대체합니다. 아래 코드는 SupportMapFragmentSupportStreetViewPanoramaFragment를 사용하여 API 12 미만의 Android 버전을 지원합니다.

런타임 시 프래그먼트가 변경되면 프래그먼트를 포함하는 Activity 클래스에 추가해야 하며 XML에 정적으로 추가하지 않아야 합니다.

관심 장소 마커 태그하기

  1. onPoiClick() 콜백의 poiMarker에서 setTag()를 호출합니다. 임의의 문자열을 전달합니다.
poiMarker.setTag("poi");

정적 SupportMapFragment를 런타임 인스턴스로 바꾸기

  1. activity_maps.xml를 열고 요소를 프래그먼트의 컨테이너 역할을 할 프레임 레이아웃으로 변경합니다.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/fragment_container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  1. MapsActivityonCreate()에서 ID로 SupportMapFragment를 찾는 코드를 삭제합니다. XML에 더 이상 정적 SupportMapFragment가 없기 때문입니다. 대신 SupportMapFragment.newInstance()를 호출하여 SupportMapFragment의 새 런타임 인스턴스를 만듭니다.
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
  1. FragmentManager와 함께 프래그먼트 트랜잭션을 사용하여 프래그먼트를 FrameLayout에 추가합니다.
getSupportFragmentManager().beginTransaction()
       .add(R.id.fragment_container, mapFragment).commit();
  1. 지도의 비동기 로드를 트리거하는 코드 줄을 유지합니다.
mapFragment.getMapAsync(this);

OnInfoWindowClickListener 설정 및 마커 태그 확인

  1. MapsActivityGoogleMap를 인수로 사용하고 void를 반환하는 setInfoWindowClickToPanorama()라는 메서드 스텁을 만듭니다.
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. OnInfoWindowClickListenerGoogleMap로 설정합니다.
map.setOnInfoWindowClickListener(
       new GoogleMap.OnInfoWindowClickListener() {
           @Override
           public void onInfoWindowClick(Marker marker) {
           }
       });
  1. onInfoWindowClick() 메서드에서 마커에 onPoiClick() 메서드에서 설정한 문자열 태그가 포함되어 있는지 확인합니다.
if (marker.getTag() == "poi") {}

SupportMapFragment를 SupportStreetViewPanoramaFragment로 바꾸기

  1. 마커에 태그가 포함된 경우 StreetViewPanoramaOptions 객체를 사용하여 스트리트 뷰 파노라마의 위치를 지정합니다. 객체의 position 속성을 전달된 마커의 위치로 설정합니다.
StreetViewPanoramaOptions options =
       new StreetViewPanoramaOptions().position(
               marker.getPosition());
  1. SupportStreetViewPanoramaFragment의 새 인스턴스를 만들어 직접 만든 options 객체를 전달합니다.
SupportStreetViewPanoramaFragment streetViewFragment
       = SupportStreetViewPanoramaFragment
       .newInstance(options);
  1. 프래그먼트 트랜잭션을 시작합니다. 프래그먼트 컨테이너의 콘텐츠를 새 프래그먼트 streetViewFragment로 바꿉니다. 뒤로 버튼을 누르면 SupportMapFragment로 다시 이동하고 앱이 종료되지 않도록 트랜잭션을 백 스택에 추가합니다.
getSupportFragmentManager().beginTransaction()
       .replace(R.id.fragment_container,
               streetViewFragment)
       .addToBackStack(null).commit();
  1. setPoiClick(). 호출 후 onMapReady()에서 setInfoWindowClickToPanorama(mMap)를 호출합니다.
  2. 앱을 실행합니다. Google 본사가 있는 마운틴 뷰와 같이 스트리트 뷰 서비스가 지원되는 도시를 확대하고 공원과 같은 관심 장소를 찾습니다. 관심 장소를 탭하여 마커를 배치하고 정보 창을 표시합니다. 정보 창을 탭하여 마커 위치의 스트리트 뷰 모드를 시작합니다. 뒤로 버튼을 눌러 지도 프래그먼트로 돌아갑니다.

Android 앱의 Google 스트리트 뷰

7. 솔루션 코드

Wander 솔루션 코드

8. 코딩 도전과제

도전과제: 스트리트 뷰 서비스가 제공되지 않는 위치에서 관심 장소에 대한 정보 창을 탭하면 검은색 화면이 표시됩니다.

9. 요약

  • 지도 API를 사용하려면 Google API 콘솔의 API 키가 필요합니다.
  • Android 스튜디오에서 Google 지도 활동 템플릿을 사용하면 앱 레이아웃에 단일 SupportMapFragment가 있는 Activity가 생성됩니다. 또한 템플릿은 앱 매니페스트에 ACCESS_FINE_PERMISSION를 추가하고, 활동에 OnMapReadyCallback를 구현하며, 필수 onMapReady() 메서드를 재정의합니다.

런타임 시 GoogleMap의 지도 유형을 변경하려면 GoogleMap.setMapType() 메서드를 사용합니다. Google 지도는 다음 지도 유형 중 하나일 수 있습니다.

  • 일반: 일반적인 도로 지도입니다. 도로, 인공 지형지물, 주요 자연 지형지물(예: 강)을 표시합니다. 도로 및 지점 라벨도 표시됩니다.
  • 하이브리드: 도로 지도가 추가된 위성 사진 데이터입니다. 도로 및 지점 라벨도 표시됩니다.
  • 위성: 데이터를 촬영합니다. 도로 및 지형지물 라벨은 표시되지 않습니다.
  • 지형: 지형 데이터. 지도에는 색상, 등고선, 라벨, 원근 음영이 포함됩니다. 도로 및 라벨도 일부 표시됩니다.
  • 없음**:** 지도가 없습니다.

Google 지도 정보:

  • 마커는 특정 지리적 위치를 나타내는 표시기입니다.
  • 마커의 기본 동작은 위치에 대한 정보가 포함된 정보 창을 표시하는 것입니다.
  • 기본적으로, 관심 지점(POI)은 해당 아이콘과 함께 기본 지도에 나타납니다. 관심 장소에는 공원, 학교, 정부 건물 등이 포함됩니다.
  • 또한 지도 유형이 normal인 경우 비즈니스 관심 장소 (상점, 음식점, 호텔 등)가 기본적으로 지도에 표시됩니다.
  • OnPoiClickListener를 사용하여 관심 장소의 클릭수를 캡처할 수 있습니다.
  • 스타일 지정 마법사를 사용하여 Google 지도에 있는 거의 모든 요소의 시각적 모양을 변경할 수 있습니다. 스타일 지정 마법사는 setMapStyle() 메서드를 사용하여 Google 지도에 전달하는 JSON 파일을 생성합니다.
  • 마커의 기본 색상을 변경하거나 기본 마커 아이콘을 맞춤 이미지로 교체하여 마커를 맞춤설정할 수 있습니다.

기타 중요 정보:

  • 지면 오버레이를 사용하여 이미지를 지리적 위치에 고정합니다.
  • GroundOverlayOptions 객체를 사용하여 이미지, 이미지의 크기(미터), 이미지의 위치를 지정합니다. 이 객체를 GoogleMap.addGroundOverlay() 메서드에 전달하여 지도에 오버레이를 설정합니다.
  • 앱에 ACCESS_FINE_LOCATION 권한이 있으면 mMap.setMyLocationEnabled(true) 메서드를 사용하여 위치 추적을 사용 설정할 수 있습니다.
  • Google 스트리트 뷰는 지정된 도로부터 커버리지 영역 전반에 걸쳐 360도 파노라마 뷰를 제공합니다.
  • StreetViewPanoramaFragment.newInstance() 메서드를 사용하여 새 스트리트 뷰 프래그먼트를 만듭니다.
  • 뷰의 옵션을 지정하려면 StreetViewPanoramaOptions 객체를 사용합니다. 객체를 newInstance() 메서드에 전달합니다.

10. 자세히 알아보기

관련 개념 문서는 9.1: Google Maps API에 있습니다.

Android 개발자 문서:

참조 문서

11. Homework

이 섹션에는 강사가 진행하는 과정의 일부로 이 Codelab을 진행하는 학생에게 출제할 수 있는 과제가 나열되어 있습니다. 다음 작업은 강사가 결정합니다.

  • 필요한 경우 과제를 할당합니다.
  • 과제 제출 방법을 학생에게 알립니다.
  • 과제를 채점합니다.

강사는 이러한 추천을 원하는 만큼 사용할 수 있으며 적절하다고 생각되는 다른 과제를 출제해도 됩니다.

이 Codelab을 직접 진행하는 경우 이러한 과제를 자유롭게 사용하여 배운 내용을 테스트해 보세요.

앱 빌드 및 실행

  1. 앱이 실행될 때 Google 지도를 로드하는 Google 지도 활동 템플릿을 사용하는 새 앱을 만듭니다.
  2. Google 지도가 로드되면 학교 위치, 집 위치 또는 나에게 의미가 있는 다른 위치로 카메라를 이동합니다.
  3. 지도에 마커 두 개(학교 위치, 집 또는 다른 의미 있는 위치)를 추가합니다.
  4. 기본 색상을 변경하거나 기본 마커 아이콘을 맞춤 이미지로 대체하여 마커 아이콘을 맞춤설정합니다.

힌트: onMapReady (GoogleMap googleMap) 문서를 참고하세요.

질문에 답하세요

질문 1

지도가 로드되어 앱에서 사용할 준비가 되었을 때 호출되는 메서드는 무엇인가요?

질문 2

앱에 Google 지도를 포함하기 위해 사용할 수 있는 Android 구성요소는 무엇인가요?

  • MapViewMapFragment
  • MapFragmentMapActivity
  • MapViewMapActivity
  • MapFragment

질문 3

Google Maps Android API는 어떤 유형의 지도를 제공하나요?

  • 일반, 하이브리드, 지형, 위성, 로드맵
  • 일반, 하이브리드, 지형, 위성, '없음'
  • 하이브리드, 지형, 위성, 로드맵 및 '없음'
  • 일반, 지형, 위성, 이미지 지도 및 '없음'

질문 4

관심 장소 (POI)에 클릭 시 기능을 추가하기 위해 어떤 인터페이스를 구현하나요?

  • GoogleMap.OnPoiListener
  • GoogleMap.OnPoiClickListener
  • GoogleMap.OnPoiClick
  • GoogleMap.OnPoiClicked

채점을 위해 앱 제출

채점자를 위한 가이드

앱에 다음 기능이 있는지 확인합니다.

  • 앱이 실행되면 Google 지도가 올바르게 표시되어 API 키가 제대로 생성되었음을 나타냅니다.
  • Google 지도가 로드되면 카메라가 학생의 집 또는 학교 위치로 이동합니다. 코드에서 이 단계는 onMapReady (GoogleMap googleMap) 콜백 메서드에서 발생해야 합니다.
  • 마커는 학생의 학교 위치와 다른 위치(예: 학생의 집)에 표시됩니다.
  • 두 마커는 맞춤설정됩니다. 예를 들어 마커는 기본 빨간색이 아닌 다른 색상을 사용하거나 맞춤 아이콘을 사용합니다.

12. 다음 Codelab

고급 Android 개발 교육 과정의 Codelab을 모두 보려면 고급 Android 개발 Codelab 방문 페이지를 참고하세요.