Освой Android играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Шаблон Google Maps Activity

Вместо предисловия

В Мурманске (очень красивое название города для кошачьего уха, мур-мур) открыли памятник коту Семёну – герою местной легенды. В бронзе увековечили домашнего кота, который шесть с половиной лет шёл на север из Москвы, где его потеряли хозяева-идиоты.

Кот Семён

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

В настоящее время API содержит векторные карты, которые быстрее загружаются, а также позволяют пользователям легко переключаться между 2D и 3D режимами, в которых карты можно вращать при помощи жестов.

С картами вообще происходят постоянные перемены. Сначала объявили устаревшими старые карты. Чтобы установить новые карты, требовалось написать отдельную статью, как скачать и установить библиотеку, как сгенерировать ключ в командной строке. К счастью, в Android Studio появился новый шаблон, который позволил избавиться от лишних слов и кода. Это уже четвёртое масштабное переписывание статьи.

Шаблон Google Maps Activity

Запускаем новый проект и в шаблонах выбираем Google Maps Activity.

В следующем шаге делаем необходимые настройки. Выбирайте Java или Kotlin. Рекомендую уже сейчас использовать Use androidx.* artifacts.

Для работы с картами нужен ключ. После создания проекта на основе шаблона будет открыт файл google_maps_api.xml, которая содержит ссылку на страницу консоли для получения ключа. Обратите внимание на полный путь файла - ..\app\src\debug\res\values\google_maps_api.xml. Если смотреть на структуру проекта, то также видно, что файл относится к версии debug.

Google Maps

На самом деле в проекте два файла google_maps_api.xml. Чтобы увидеть второй файл, переключитесь в режим Project files и в папке release увидите второй файл.

Google Maps

Для опытов мы можем использовать отладочный вариант файла, а когда вы будете создавать полноценное приложение с выкладыванием в Google Play, то вам придётся сгенерировать новый ключ разработчика.

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

В следующем окне нужно нажать кнопку Создать ключ API, чтобы получить заветный ключик.

Ключ начинается на AIza, его нужно скопировать, вернуться обратно в файл google_maps_api.xml и вставить вместо текста YOUR_KEY_HERE.

Сам файл хранит строковый ресурс google_maps_key, который используется в манифесте внутри секции <application> в секции meta-data.

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

Ручная подготовка

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

Для работы с картой необходимо получить ключи - один для debug-версии, а второй для release-версии вашего приложения. Без ключа компонент не загрузит необходимые для отображения карты фрагменты.

Для получения ключа нужно указать SHA1-слепок сертификата (раньше просили MD5-слепок), использующегося для подписи приложения. Как правило, подписывать свои приложения вы будете с помощью двух сертификатов — отладочного, созданного по умолчанию, и реального.

Рассмотрим процес получения ключа для debug-версии. Найдите на своем компьютере файл debug.keystore. Для Windows 7 это будет:

C:\Users\<user>\.android\debug.keystore

Для OS X and Linux:

~/.android/debug.keystore

Далее вы должны получить ключ при помощи утилиты keytool, которая идёт вместе с Java и находится примерно по такому пути "C:\Program Files\Java\jdk1.7.0_45\jre\bin".

Запускайте командную строку или откройте в студии вкладку Terminal и выполняйте следующую команду:

"C:\Program Files\Java\jdk1.7.0_45\jre\bin\keytool" -list -v -keystore C:\Users\klimo_000\.android\debug.keystore -alias androiddebugkey -storepass android -keypass android

В итоге у вас появится сгенерированная SHA1-строка.

Далее нужно перейти по адресу https://console.developers.google.com/project и создать новый проект. Там нужно задать различные свойства, включить карты и получить ключ. Гугл иногда меняет правила, поэтому лучше почитать у них свежую документацию о получении ключа.

Для подписанных приложений, которые вы собираетесь размещать на Google Play, принцип такой же, только используется не debug.keystore, а хранилище ключей:

keytool -list -v -keystore mystore.keystore

В build.gradle прописываем зависимость:


implementation 'com.google.android.gms:play-services-maps:16.1.0'

В манифесте разрешения.


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

На этом предварительная подготовка завершена. Можно запустить проект. Если версия Сервисы Google Play устарела, то на экране появится кнопка Обновить. Если на устройстве свежая версия, то запустится пример с картой.

В текущей версии шаблона указаны координаты Сиднея, Австралия (раньше была карта в районе Африки с маркером в точке 0, 0) . Нажав на маркер, вы увидите всплывающий текст Marker in Sydney. Карту можно увеличивать двойным щелчком, а также сдвигать/раздвигать пальцами.

Познакомимся поближе с проектом. Для разметки используется фрагмент с классом Для разметки используется фрагмент с классом com.google.android.gms.maps.SupportMapFragment.


<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          xmlns:map="http://schemas.android.com/apk/res-auto"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:id="@+id/map"
          tools:context=".MapsActivity"
          android:name="com.google.android.gms.maps.SupportMapFragment"/>

Код активности.


package ru.alexanderklimov.googlemap;

import android.os.Bundle;

import androidx.fragment.app.FragmentActivity;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }
}	
	  

package ru.alexanderklimov.places

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        val mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }

    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap

        // Add a marker in Sydney and move the camera
        val sydney = LatLng(-34.0, 151.0)
        mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
    }
}

Класс MapsActivity наследуется от AppCompatActivity (в Java-варианте FragmentActivity) и использует интерфейс OnMapReadyCallback.

В методе onCreate() получаем доступ к фрагменту и загружаем карту в асинхронном режиме через метод getMapAsync().

Метод onMapReady() является частью интерфейса OnMapReadyCallback. В этом методе можно писать код, когда карта готова к использованию. В примере добавляется маркер (метод addMarker()) в указанной точке (через объект LatLng) с указанием текста (метод title()). Метод moveCamera() перемещает карту в указанную позицию и мы можем видеть сразу нужное место.

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


mMap.addMarker(new MarkerOptions().position(sydney).title("Это Сидней")
        .snippet("В Сиднее много котов"));

mMap.addMarker(MarkerOptions()
    .position(sydney).title("Marker in Sydney")
    .snippet("В Сиднее много котов"))

Подсказка появляется под описанием маркера с другим цветом. Если на карте должно быть несколько маркеров, то просто вызываете методы addMarker() несколько раз с разными параметрами.

Sydney

Дополнительное чтение

Обсуждение урока на форуме

Google Maps. Другие настройки карты

Google Maps. Продвинутые приёмы

Документация по Google Map

Реклама