Продвинутый Android в Kotlin 04.1: Android Google Maps

Эта практическая работа входит в курс «Advanced Android in Kotlin». Вы получите максимальную пользу от этого курса, выполняя задания последовательно, но это не обязательно. Все практическая работа курса перечислены на целевой странице практической работы «Advanced Android in Kotlin» .

Создание приложений с помощью Google Карт позволяет добавлять в них новые функции, такие как спутниковые снимки, удобный пользовательский интерфейс для управления картами, отслеживание местоположения и маркеры местоположения. Вы можете расширить возможности стандартных Google Карт, отображая информацию из собственного набора данных, например, местоположение популярных мест для рыбалки или скалолазания. Вы также можете создавать игры, в которых игрок исследует физический мир, например, в поисках сокровищ или даже в играх с дополненной реальностью.

На этом уроке вы создадите приложение Google Maps под названием Wander, которое отображает настроенные карты и показывает местоположение пользователя.

Предпосылки

Знание следующего:

  • Как создать простое приложение для Android и запустить его с помощью Android Studio.
  • Как создавать и управлять ресурсами, такими как строки.
  • Как рефакторить код и переименовать переменные с помощью Android Studio.
  • Как пользоваться картой Google как пользователь.
  • Как установить разрешения времени выполнения.

Чему вы научитесь

  • Как получить ключ API из Google API Console и зарегистрировать ключ в своем приложении
  • Как интегрировать Google Maps в ваше приложение
  • Как отображать различные типы карт
  • Как стилизовать карту Google
  • Как добавить маркеры на карту
  • Как предоставить пользователю возможность разместить маркер на точке интереса (POI)
  • Как включить отслеживание местоположения
  • Как создать приложение The Wander со встроенной картой Google
  • Как создавать пользовательские функции для вашего приложения, такие как маркеры и стили
  • Как включить отслеживание местоположения в вашем приложении

В этой лабораторной работе вы создадите приложение Wander , которое отображает карту Google с пользовательским стилем. Приложение Wander позволяет вам отмечать места на карте маркерами, добавлять наложения и видеть своё местоположение в режиме реального времени.

Для Maps SDK для Android требуется ключ API. Чтобы получить ключ API, зарегистрируйте свой проект на странице API и сервисы . Ключ API привязан к цифровому сертификату, который связывает приложение с его автором. Подробнее об использовании цифровых сертификатов и подписи приложения см. в разделе «Подпись приложения» .

В этой лабораторной работе вы используете ключ API для отладочного сертификата. Отладочный сертификат изначально небезопасен, как описано в разделе «Подписание отладочной сборки» . Для опубликованных приложений Android, использующих Maps SDK для Android, требуется второй ключ API: ключ для сертификата выпуска. Подробнее о получении сертификата выпуска см. в разделе «Получение ключа API» .

В Android Studio есть шаблон активности Google Карт, который генерирует полезный код шаблона. Этот код включает файл google_maps_api.xml , содержащий ссылку, упрощающую получение ключа API.

Шаг 1: Создайте проект Wander с помощью шаблона карт

  1. Создайте новый проект Android Studio.
  2. Выберите шаблон «Действия Google Карт» .

  1. Назовите проект Wander .
  2. Установите минимальный уровень API на API 19. Убедитесь, что выбран язык Kotlin .
  3. Нажмите кнопку Готово .
  4. После завершения сборки приложения взгляните на свой проект и следующие файлы, связанные с картами, которые Android Studio создает для вас:

google_maps_api.xml — этот файл конфигурации используется для хранения вашего ключа API. Шаблон генерирует два файла google_maps_api.xml : один для отладки и один для выпуска. Файл ключа API для сертификата отладки находится в папке src/debug/res/values . Файл ключа API для сертификата выпуска находится в папке src/release/res/values . В этой лабораторной работе используется только сертификат отладки.

activity_maps.xml — этот файл макета содержит один фрагмент, заполняющий весь экран. Класс SupportMapFragment является подклассом класса Fragment . SupportMapFragment — это самый простой способ разместить карту в приложении. Это оболочка для представления карты, которая автоматически обрабатывает необходимые требования жизненного цикла.

Вы можете включить SupportMapFragment в файл макета, используя тег <fragment> в любой ViewGroup с дополнительным атрибутом name .

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

MapsActivity.java — файл MapsActivity.kt создаёт экземпляр SupportMapFragment в методе onCreate() и использует метод getMapAsync () класса для автоматической инициализации системы карт и представления. Активность, содержащая SupportMapFragment , должна реализовывать интерфейс OnMapReadyCallback и метод onMapReady() этого интерфейса. Метод onMapReady() вызывается при загрузке карты.

Шаг 2: Получите ключ API

  1. Откройте отладочную версию файла google_maps_api.xml .
  2. В файле найдите комментарий с длинным URL-адресом. Параметры URL-адреса включают конкретную информацию о вашем приложении.
  3. Скопируйте и вставьте URL-адрес в браузер.
  4. Следуйте инструкциям по созданию проекта на странице «API и сервисы» . Благодаря параметрам в указанном URL-адресе страница автоматически включает Maps SDK для Android.
  5. Нажмите «Создать ключ API» .
  6. На следующей странице перейдите в раздел «Ключи API» и нажмите на ключ, который вы только что создали.
  7. Нажмите «Ограничить ключ» и выберите Maps SDK для Android, чтобы ограничить использование ключа приложениями Android.
  8. Скопируйте сгенерированный API-ключ. Он начинается с « AIza" .
  9. В файле google_maps_api.xml вставьте ключ в строку google_maps_key там, где указано YOUR_KEY_HERE .
  10. Запустите приложение. В вашей активности должна появиться встроенная карта с маркером Сиднея, Австралия. (Маркер Сиднея является частью шаблона, и вы сможете изменить его позже.)

Шаг 3: Переименуйте mMap

У MapsActivity есть приватная var lateinit mMap , которая имеет тип GoogleMap . Чтобы соответствовать правилам именования Kotlin, измените имя mMap на map .

  1. В MapsActivity щелкните правой кнопкой мыши mMap и выберите Рефакторинг > Переименовать...

  1. Измените имя переменной на map .

Обратите внимание, что все ссылки на mMap в функции onMapReady() также изменяются на map .

Google Maps включает в себя несколько типов карт: обычные, гибридные, спутниковые, карты рельефа и «отсутствуют» (карта вообще отсутствует).

Нормальная карта

Спутниковая карта

Гибридная карта

Карта местности

Каждый тип карты предоставляет различную информацию. Например, при использовании карт для навигации в автомобиле удобно видеть названия улиц, поэтому можно использовать стандартный вариант. В пешем походе карта рельефа может помочь определить, какой подъём вам ещё предстоит пройти, чтобы добраться до вершины.

В этом задании вы:

  1. Добавьте панель приложения с меню параметров, позволяющим пользователю изменять тип карты.
  2. Переместите начальную точку карты в свое домашнее местоположение.
  3. Добавить поддержку маркеров, которые обозначают отдельные местоположения на карте и могут включать метку.

Добавить меню для типов карт

На этом этапе вы добавляете панель приложения с меню параметров, которое позволяет пользователю изменять тип карты.

  1. Чтобы создать новый XML-файл меню, щелкните правой кнопкой мыши по каталогу res и выберите «Создать» > «Файл ресурсов Android» .
  2. В диалоговом окне назовите файл map_options .
  3. Выберите Меню для типа ресурса.
  4. Нажмите ОК .
  5. На вкладке «Код» замените код в новом файле следующим кодом, чтобы создать пункты меню карты. Тип карты «none» опущен, поскольку «none» приводит к полному отсутствию карты. Этот шаг приводит к ошибке, но она будет устранена на следующем шаге.
<?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. В 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>
  1. В MapsActivity переопределите метод onCreateOptionsMenu() и добавьте меню из файла ресурсов map_options .
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. В 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)
}
  1. Запустите приложение.
  2. Щелкните Чтобы изменить тип карты, обратите внимание на то, как меняется внешний вид карты в разных режимах.

По умолчанию функция обратного вызова onMapReady() включает код, который устанавливает маркер в Сиднее (Австралия), где были созданы Google Карты. Функция обратного вызова по умолчанию также анимирует карту, перемещаясь в сторону Сиднея.

В этом задании вы перемещаете камеру карты к своему дому, масштабируете ее до указанного уровня и размещаете там маркер.

Шаг 1: Увеличьте масштаб изображения до своего дома и добавьте маркер.

  1. В файле MapsActivity.kt найдите метод onMapReady() . Удалите из него код, который устанавливает маркер в Сиднее и перемещает камеру. Вот как должен выглядеть ваш метод.
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. Найдите широту и долготу вашего дома, следуя этим инструкциям .
  2. Создайте значение широты и значение долготы и введите их значения с плавающей точкой.
val latitude = 37.422160
val longitude = -122.084270
  1. Создайте новый объект LatLng с именем homeLatLng . В объект homeLatLng передайте только что созданные вами значения.
val homeLatLng = LatLng(latitude, longitude)
  1. Создайте val масштаба карты. Используйте уровень масштабирования 15f.
val zoomLevel = 15f

Уровень масштабирования управляет степенью приближения карты. Следующий список даёт представление о том, какой уровень детализации отображается на каждом уровне масштабирования:

  • 1 : Мир
  • 5 : Суша/континент
  • 10 : Город
  • 15 : Улицы
  • 20 : Здания
  1. Переместите камеру в homeLatLng , вызвав функцию moveCamera() объекта map и передайте объект CameraUpdate с помощью CameraUpdateFactory.newLatLngZoom() . Передайте объект homeLatLng и zoomLevel .
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. Добавьте маркер на карту в 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))
}
  1. Запустите приложение. Карта должна переместиться к вашему дому, увеличиться до нужного уровня и отметить его маркером.

Шаг 2: Разрешите пользователям добавлять маркер с помощью долгого нажатия

На этом этапе вы добавляете маркер, когда пользователь касается и удерживает местоположение на карте.

  1. Создайте заглушку метода в MapsActivity с именем setMapLongClick() , который принимает GoogleMap в качестве аргумента.
  2. Присоедините прослушиватель setOnMapLongClickListener к объекту карты.
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. В методе setOnMapLongClickListener() вызовите метод addMarker() . Передайте новый объект MarkerOptions с позицией, заданной переданным значением LatLng .
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. В конце метода onMapReady() вызовите setMapLongClick() с map .
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. Запустите приложение.
  2. Нажмите и удерживайте карту, чтобы разместить маркер в определенном месте.
  3. Коснитесь маркера, и он окажется в центре экрана.

Шаг 3: Добавьте информационное окно для маркера.

На этом этапе вы добавляете InfoWindow , которое отображает координаты маркера при касании маркера.

  1. В setMapLongClick()setOnMapLongClickListener() создайте val для snippet . Snippet — это дополнительный текст, отображаемый после заголовка. Ваш snippet отображает широту и долготу маркера.
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)
       )
   }
}
  1. В addMarker() задайте title маркера как Dropped Pin dropped_pin используя строковый ресурс R.string. .
  2. Установите для маркера 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)
              
       )
   }
}
  1. Запустите приложение.
  2. Нажмите и удерживайте карту, чтобы установить маркер местоположения.
  3. Нажмите на маркер, чтобы открыть информационное окно.

Шаг 4: Добавьте прослушиватель POI

По умолчанию точки интереса (POI) отображаются на карте вместе с соответствующими значками. К ним относятся парки, школы, правительственные здания и многое другое. Если выбран normal тип карты, на карте также отображаются деловые объекты интереса (POI). Такие объекты представляют собой предприятия, такие как магазины, рестораны и отели.

На этом этапе вы добавляете на карту слушатель GoogleMap.OnPoiClickListener . Этот прослушиватель щелчков мгновенно размещает маркер на карте, когда пользователь нажимает на точку интереса (POI). Он также отображает информационное окно с названием точки интереса.

  1. Создайте заглушку метода в MapsActivity с именем setPoiClick() , который принимает GoogleMap в качестве аргумента.
  2. В методе setPoiClick() установите OnPoiClickListener для переданного объекта GoogleMap .
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. В setOnPoiClickListener() создайте val poiMarker для маркера.
  2. Установите его в качестве маркера с помощью map.addMarker() а MarkerOptions задайте в качестве title имя точки интереса.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. В функции setOnPoiClickListener() вызовите showInfoWindow() для poiMarker , чтобы немедленно отобразить информационное окно.
poiMarker.showInfoWindow()

Ваш окончательный код для функции setPoiClick() должен выглядеть следующим образом.

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. В конце onMapReady() вызовите setPoiClick() и передайте map .
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. Запустите приложение и найдите точку интереса, например парк или кофейню.
  2. Нажмите на точку интереса, чтобы поместить на нее маркер и отобразить название точки интереса в информационном окне.

Вы можете настраивать Google Maps различными способами, придавая своей карте уникальный вид.

Вы можете настроить объект MapFragment , используя доступные атрибуты XML , как и любой другой фрагмент. Однако на этом этапе вы настраиваете внешний вид и содержание MapFragment , используя методы объекта GoogleMap .

Чтобы создать индивидуальный стиль для вашей карты, вы генерируете JSON-файл, определяющий, как отображаются объекты на карте. Вам не нужно создавать этот JSON-файл вручную. Google предоставляет мастер стилей Maps Platform , который генерирует JSON-файл после того, как вы визуально стилизуете карту. В этом задании вы оформляете карту в ретро-стиле, то есть используете винтажные цвета и добавляете цветные дороги.

Шаг 1: Создайте стиль для вашей карты

  1. Перейдите по адресу https://mapstyle.withgoogle.com/ в вашем браузере.
  2. Выберите Создать стиль .
  3. Выберите Ретро .

  1. Нажмите Дополнительные параметры .

  1. В списке Тип объекта выберите Дорога > Насыпь .
  2. Измените цвет дорог на любой выбранный вами (например, розовый).

  1. Нажмите кнопку Готово .

  1. Скопируйте JSON-код из полученного диалогового окна и, если хотите, сохраните его в виде текстовой заметки для использования на следующем шаге.

Шаг 2: Добавьте стиль к вашей карте.

  1. В Android Studio, в разделе res В каталоге создайте каталог ресурсов и назовите его raw . Ресурсы каталога raw используются как JSON-код.
  2. Создайте файл в res/raw с именем map_style.json .
  3. Вставьте сохранённый JSON-код в новый файл ресурсов.
  4. В MapsActivity создайте переменную класса TAG над методом onCreate() . Она будет использоваться для ведения журнала.
private val TAG = MapsActivity::class.java.simpleName
  1. Также в MapsActivity создайте функцию setMapStyle() , которая принимает GoogleMap .
  2. В setMapStyle() добавьте блок try{} .
  3. В блоке try{} создайте val success для успешного выполнения стилизации. (Вы добавляете следующий блок catch.)
  4. В блоке try{} задайте стиль JSON для карты, вызовите setMapStyle() для объекта GoogleMap . Передайте объект MapStyleOptions , который загрузит JSON-файл.
  5. Присвойте результат параметру 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
           )
       )
   }
}
  1. Добавьте оператор if, устанавливающий значение false для success . Если стилизация не удалась, выведите в журнал сообщение о том, что разбор не удался.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. Добавьте блок 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)
   }
}
  1. Наконец, вызовите метод setMapStyle() в методе onMapReady() передав ему объект GoogleMap .
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. Запустите приложение.
  2. Переведите карту в normal режим, и новый стиль с ретро-темой и дорогами выбранного вами цвета должен быть заметен.

Шаг 3: Выберите стиль маркера

Вы можете ещё больше персонализировать свою карту, стилизовав маркеры. На этом этапе вы измените стандартные красные маркеры на что-то более стильное.

  1. В методе 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))
   )
}
  1. Запустите приложение. Маркеры, появляющиеся после долгого нажатия, теперь окрашены в синий цвет. Обратите внимание, что маркеры точек интереса (POI) по-прежнему красные, поскольку вы не добавили стили к методу onPoiClick() .

Один из способов персонализировать карту Google — рисовать поверх неё. Этот приём полезен, если вы хотите выделить определённый тип местоположения, например, популярные места для рыбалки.

  • Фигуры: на карту можно добавлять полилинии , многоугольники и круги .
  • Объекты GroundOverlay : Наземное наложение — это изображение, закреплённое на карте. В отличие от маркеров, наземные наложения ориентированы на поверхность Земли, а не на экран. Поворот, наклон или масштабирование карты изменяют ориентацию изображения. Наземные наложения полезны, когда требуется закрепить отдельное изображение в определённой области карты.

Шаг: Добавьте наложение земли

В этом задании вы добавите наземную накладку в форме Android к своему домашнему местоположению.

  1. Загрузите это изображение Android и сохраните его в папке res/drawable . (Убедитесь, что имя файла — android.png .)

  1. В onMapReady() после вызова перемещения камеры в положение вашего дома создайте объект GroundOverlayOptions .
  2. Назначьте объект переменной androidOverlay .
val androidOverlay = GroundOverlayOptions()
  1. Используйте метод BitmapDescriptorFactory.fromResource() для создания объекта BitmapDescriptor из загруженного ресурса изображения.
  2. Передайте полученный объект BitmapDescriptor в метод image() объекта GroundOverlayOptions .
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. Создайте float overlaySize указывающий ширину нужного наложения в метрах. В этом примере хорошо подойдёт ширина 100f .

Задайте свойство position для объекта GroundOverlayOptions , вызвав метод position() , и передайте объект homeLatLng и overlaySize .

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. Вызовите addGroundOverlay() для объекта GoogleMap и передайте ему объект GroundOverlayOptions .
map.addGroundOverlay(androidOverlay)
  1. Запустите приложение.
  2. Измените значение zoomLevel на 18f, чтобы увидеть изображение Android в виде наложения.

Пользователи часто используют Google Карты, чтобы увидеть своё текущее местоположение. Чтобы отобразить местоположение устройства на карте, можно использовать слой данных о местоположении .

Слой данных о местоположении добавляет «Моё местоположение» на карту. При нажатии кнопки карта центрируется на местоположении устройства. Местоположение отображается синей точкой, если устройство неподвижно, и синим шевроном, если устройство движется.

В этой задаче вы включите слой данных о местоположении.

Шаг: Запросите разрешение на определение местоположения

Для включения отслеживания местоположения в Google Картах требуется всего одна строка кода. Однако необходимо убедиться, что пользователь предоставил разрешения на определение местоположения (используя модель разрешений времени выполнения).

На этом этапе вы запрашиваете разрешения на определение местоположения и включаете отслеживание местоположения.

  1. Убедитесь, что в файле AndroidManifest.xml уже присутствует разрешение FINE_LOCATION . Android Studio добавила это разрешение при выборе шаблона Google Maps.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. В MapsActivity создайте переменную класса REQUEST_LOCATION_PERMISSION .
private val REQUEST_LOCATION_PERMISSION = 1
  1. Чтобы проверить, предоставлены ли разрешения, создайте метод isPermissionGranted() в MapsActivity . В этом методе проверяется, предоставил ли пользователь разрешение.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. Чтобы включить отслеживание местоположения в приложении, создайте метод enableMyLocation() в MapsActivity , который не принимает аргументов и ничего не возвращает. Внутри него проверьте наличие разрешения 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
       )
   }
}
  1. Вызовите enableMyLocation() из обратного вызова onMapReady() , чтобы включить слой местоположения.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. Переопределите метод onRequestPermissionsResult() . Если requestCode равен REQUEST_LOCATION_PERMISSION , разрешение предоставляется, а массив grantResults непустой и в его первом слоте указано PackageManager.PERMISSION_GRANTED , вызовите enableMyLocation() .
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. Запустите приложение. Должно появиться диалоговое окно с запросом на доступ к данным о местоположении устройства. Дайте разрешение.

Текущее местоположение устройства теперь отображается на карте синей точкой. Обратите внимание на кнопку определения местоположения. Если вы переместите карту от своего местоположения и нажмете эту кнопку, она снова центрируется относительно местоположения устройства.

Загрузите код для готовой лабораторной работы.

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps


Кроме того, вы можете загрузить репозиторий в виде zip-файла, распаковать его и открыть в Android Studio.

Скачать zip-архив

  • Для использования API Карт вам понадобится ключ API из консоли API Google .
  • В Android Studio использование шаблона Activity Google Maps генерирует Activity с одним фрагментом SupportMapFragment в макете приложения. Шаблон также добавляет ACCESS_FINE_PERMISSION в манифест приложения, реализует OnMapReadyCallback в вашей Activity и переопределяет требуемый метод onMapReady() .

Чтобы изменить тип карты GoogleMap во время выполнения, используйте метод GoogleMap.setMapType() . Карта Google может быть одного из следующих типов:

  • Обычная : Типичная дорожная карта. Показаны дороги, некоторые объекты, созданные человеком, и важные природные объекты, такие как реки. Также видны обозначения дорог и объектов.
  • Гибрид : данные спутниковых снимков с добавлением дорожных карт. Также видны обозначения дорог и объектов.
  • Спутник : Данные фотографии. Обозначения дорог и объектов не видны.
  • Рельеф : топографические данные. Карта включает цвета, контурные линии и подписи, а также перспективную штриховку. Также видны некоторые дороги и подписи.
  • Нет : нет фрагментов базовой карты.

О Google Картах:

  • Маркер — это указатель определенного географического местоположения.
  • При нажатии на маркер по умолчанию отображается информационное окно с данными о местоположении.
  • По умолчанию точки интереса (POI) отображаются на базовой карте вместе с соответствующими значками. К ним относятся парки, школы, правительственные здания и многое другое.
  • Кроме того, на normal карте по умолчанию отображаются деловые объекты (магазины, рестораны, гостиницы и т. д.).
  • Вы можете фиксировать клики по POI с помощью OnPoiClickListener .
  • Вы можете изменить внешний вид практически любого элемента карты Google с помощью мастера стилей . Мастер стилей генерирует JSON-файл, который вы передаёте в карту Google с помощью метода setMapStyle() .
  • Вы можете настроить маркеры, изменив цвет по умолчанию или заменив значок маркера по умолчанию на пользовательское изображение.

Другая важная информация:

  • Используйте наложение земной поверхности , чтобы привязать изображение к географическому положению.
  • Используйте объект GroundOverlayOptions для указания изображения, его размера в метрах и положения. Передайте этот объект методу GoogleMap.addGroundOverlay() , чтобы установить наложение на карту.
  • Если у вашего приложения есть разрешение ACCESS_FINE_LOCATION , вы можете включить отслеживание местоположения, установив map.isMyLocationEnabled = true .
  • Это не рассматривается в данной практической работе, но вы можете предоставить дополнительную информацию о местоположении с помощью Google Street View , который представляет собой панорамную фотографию заданного места с возможностью навигации.

Документация для разработчиков Android:

Справочная документация:

Ссылки на другие практические занятия по этому курсу см. на целевой странице практических занятий по курсу Advanced Android in Kotlin .