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

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

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

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

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

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

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

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

  • Как получить ключ API из консоли API Google и зарегистрировать ключ в своем приложении
  • Как интегрировать карту 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 включает шаблон активности 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 создает экземпляр 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. Запустите свое приложение. В своей деятельности вы должны увидеть встроенную карту с маркером, установленным в Сиднее, Австралия. (Маркер Сиднея является частью шаблона, и вы измените его позже.)

34dc9dd877c90996.png

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

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

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

e713ccb3384450c6.png

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

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

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

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

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

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

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

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

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

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

  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. Нажмите 428da163b831115b.png чтобы изменить тип карты. Обратите внимание, как внешний вид карты меняется в разных режимах.

6fa42970d87f5dc7.png

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

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

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, используя R.string. Строковый ресурс dropped_pin .
  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) отображаются на карте вместе с соответствующими значками. К POI относятся парки, школы, правительственные здания и многое другое. Если для карты установлен normal тип, на карте также отображаются бизнес-объекты. Бизнес-POI представляют собой такие предприятия, как магазины, рестораны и отели.

На этом этапе вы добавите на карту GoogleMap.OnPoiClickListener . Этот прослушиватель кликов сразу же размещает маркер на карте, когда пользователь щелкает POI. Прослушиватель кликов также отображает информационное окно, содержащее имя 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. Запустите приложение и найдите POI, например парк или кафе.
  2. Коснитесь POI, чтобы поместить на него маркер и отобразить название POI в информационном окне.

f4b0972c75d5fa5f.png

6. Задача: стилизовать свою карту

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

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

Чтобы создать индивидуальный стиль для вашей карты, вы создаете файл JSON, который определяет, как отображаются объекты на карте. Вам не нужно создавать этот файл JSON вручную. Google предоставляет мастер стилизации платформы Карт , который генерирует 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 был ложным. Если стилизация не удалась, распечатайте журнал о том, что синтаксический анализ не удался.
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 . Наложение земли — это изображение, прикрепленное к карте. В отличие от маркеров, наземные наложения ориентированы на поверхность Земли, а не на экран. Вращение, наклон или масштабирование карты меняет ориентацию изображения. Наземные наложения полезны, когда вы хотите зафиксировать одно изображение в одной области карты.

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

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

  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, чтобы увидеть свое текущее местоположение. Чтобы отобразить местоположение устройства на карте, вы можете использовать слой данных о местоположении .

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

f317f84dcb3ac3a1.png

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

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

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

Для включения отслеживания местоположения в Картах 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. Чтобы проверить, предоставлены ли разрешения, создайте в 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» .