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

1. Прежде чем начать

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

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

Предварительные требования

Знание следующих знаний:

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

Что вы узнаете

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

2. Обзор приложения

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

5b12eda7f467bc2f.png

3. Задача: Настроить проект и получить ключ API.

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

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

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

Шаг 1: Создайте проект Wander, используя шаблон карт.

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

d6b874bb19ea68cd.png

  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 в методе onCreate() создается экземпляр SupportMapFragment , а для автоматической инициализации системы карт и представления используется метод getMapAsync () класса. Активность, содержащая SupportMapFragment , должна реализовывать интерфейс OnMapReadyCallback и метод onMapReady() этого интерфейса. Метод onMapReady() вызывается при загрузке карты.

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

  1. Откройте отладочную версию файла google_maps_api.xml .
  2. В файле найдите комментарий с длинным URL-адресом. Параметры URL-адреса содержат конкретную информацию о вашем приложении.
  3. Скопируйте и вставьте URL-адрес в браузер.
  4. Следуйте инструкциям, чтобы создать проект на странице «API и сервисы» . Благодаря параметрам в предоставленном URL-адресе, страница автоматически включает 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. Запустите приложение. В вашем приложении должна отобразиться встроенная карта с маркером, указывающим на Сидней, Австралия. (Маркер Сиднея является частью шаблона, и вы можете изменить его позже.)

34dc9dd877c90996.png

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

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

  1. В MapsActivity щелкните правой кнопкой мыши mMap и выберите Refactor > Rename...

e713ccb3384450c6.png

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

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

4. Задание: Добавить типы карт

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

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

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

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

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

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

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

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

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

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

  1. Чтобы создать новый XML-файл меню, щелкните правой кнопкой мыши по каталогу res и выберите New > Android Resource File .
  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. Нажмите 428da163b831115b.png Чтобы изменить тип карты. Обратите внимание, как меняется внешний вид карты в разных режимах.

6fa42970d87f5dc7.png

5. Задание: Добавить маркеры

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

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

Шаг 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. Запустите приложение. Карта должна переместиться к вашему дому, увеличить масштаб до нужного уровня и поставить метку на вашем доме.

fc939024778ee76.png

Шаг 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. Нажмите на маркер, чтобы расположить его по центру экрана.

4ff8d1c1db3bca9e.png

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

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

  1. В setMapLongClick()setOnMapLongClickListener() создайте val для 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. Нажмите на маркер, чтобы открыть информационное окно.

63f210e6e47dfa29.png

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

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

На этом шаге вы добавляете на карту обработчик 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 , равный названию точки интереса (POI).
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. Коснитесь объекта интереса (POI), чтобы установить на нем маркер и отобразить его название в информационном окне.

f4b0972c75d5fa5f.png

6. Задание: Оформите свою карту.

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

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

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

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

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

208b3d3aeab0d9b6.png

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

4a35faaf9535ee82.png

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

92c3293749293a4c.png

  1. Нажмите «Готово» .

f1bfe8585eb69480.png

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

3c32168b299d6420.png

Шаг 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 для условия success , если значение равно false. Если стилизация не удалась, выведите в лог сообщение о том, что анализ не удался.
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 режим, и новое оформление станет видимым: ретро-тематика и дороги выбранного вами цвета.

b59d6cb81f02a14f.png

Шаг 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() .

b9916bca3c367e3.png

7. Задание: Добавить наложение

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

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

Шаг: Добавьте наложение грунта.

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

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

61fabd56a0841b44.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 в качестве наложения.

b1b25b0acd6a9807.png

8. Задача: Включить отслеживание местоположения.

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

Слой с данными о местоположении добавляет на карту значок «Мое местоположение» .

f317f84dcb3ac3a1.png

Когда пользователь нажимает кнопку, карта центрируется на местоположении устройства. Местоположение отображается в виде синей точки, если устройство неподвижно, и в виде синей стрелки, если устройство движется.

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

Шаг: Запросите разрешение на доступ к местоположению.

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

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

  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. Чтобы проверить, предоставлены ли разрешения, создайте в MapsActivity метод с именем isPermissionGranted() . В этом методе проверьте, предоставил ли пользователь разрешение.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. Чтобы включить отслеживание местоположения в вашем приложении, создайте в 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
       )
   }
}
  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. Запустите приложение. Должно появиться диалоговое окно с запросом на доступ к местоположению устройства. Предоставьте разрешение.

da7e23e00ec762c1.png

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

5b12eda7f467bc2f.png

9. Код решения

Скачайте код для готового практического занятия.

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

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

10. Резюме

Поздравляем! Вы добавили карту Google в Android-приложение на Kotlin и оформили её.

11. Узнайте больше

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

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

12. Следующая практическая работа.

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