Вступление
Без сомнения, карты являются одним из самых полезных инструментов для пользователей, когда они включены в приложение. Это первое в серии пособие, посвященное Google Maps v2 для Android. Он будет включать в себя настройку API Карт Google через консоль разработчика Google, включая фрагмент карты в ваших приложениях, отображение местоположения пользователя, добавление маркеров, рисование на карте и некоторые общие методы, которые добавят полезность в ваше приложение. Весь код для этого урока можно найти на GitHub .
1. Настройка консоли разработчика
Чтобы использовать API Карт Google, необходимо зарегистрировать свое приложение в консоли разработчика Google и включить API. Для этого перейдите в консоль разработчика Google . Если у вас уже есть проект, вы можете пропустить следующий раздел. Если нет, вы можете следовать и создать новый проект для вашего приложения карт.
Шаг 1: Создание проекта
Чтобы создать новый проект, нажмите синюю кнопку « Создать проект» в верхнем левом углу экрана. Если вы не видите кнопку « Создать проект» , найдите кнопку « Создать пустой проект» .

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

После нажатия кнопки « Создать » в правом нижнем углу страницы появляется диалоговое окно с индикатором загрузки во время создания проекта.
Шаг 2. Включение API Карт
Когда проект создан или вы выбрали существующий проект, вы попадете на экран обзора проекта. Отсюда вы захотите развернуть APIs и элемент авторизации на левой навигационной панели и нажать на API .

Хотя на этом экране есть окно поиска, вы заметите, что Google разместил элементы API Карт в верхней части центральной колонки, чтобы разработчики могли получить к ним доступ. Для этого руководства щелкните элемент под названием « Google Maps Android API» под заголовком « Google Maps APIs» .

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

Шаг 3. Создание ключа API Android
После того, как вы включили API Карт, щелкните элемент « Учетные данные» в разделе « API-интерфейсы и авторизация» на боковой панели навигации, чтобы получить ключ для доступа к API-интерфейсу Карт в вашем приложении. Когда вы увидите диалоговое окно Credentials , нажмите синюю кнопку Add Credentials и выберите API Key .

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

На следующем экране нажмите Добавить имя пакета и отпечаток пальца . Это обеспечивает два поля: одно для добавления имени пакета, а другое для добавления SHA1 из ключа подписи вашего приложения .
Для этого урока я буду использовать имя пакета com.tutsplus.mapsdemo . Чтобы получить подпись SHA1, вам нужно открыть терминал или командную строку и перейти к расположению ключа подписи вашего приложения. Это может быть либо ключ релиза, либо debug.keystore . Вы можете создать SHA1 с помощью следующей команды:
|
1
|
keytool -list -v -keystore debug.keystore
|

После того, как вы создали свой ключ SHA1 и ввели его в текстовое поле, нажмите синюю кнопку Создать . Затем вы увидите диалоговое окно, содержащее ключ API, который необходимо добавить в приложение Android для доступа к API Карт.

2. Настройка проекта Android
На этом этапе вы можете создать исходный проект Android с тем же именем пакета, которое вы использовали для создания ключа API. Как только ваш проект создан, откройте файл build.gradle . Вам необходимо импортировать библиотеку Play Services для карт. В этом примере вам также необходимо импортировать локации из библиотеки Play Services, чтобы установить начальную позицию для вашей карты. Поместите следующие строки в узел dependencies файла build.gradle .
|
1
2
|
compile ‘com.google.android.gms:play-services-maps:7.8.0’
compile ‘com.google.android.gms:play-services-location:7.8.0’
|
После того, как вы импортировали свои библиотеки, вы можете закрыть build.gradle и открыть файл AndroidManifest.xml . Над узлом application необходимо объявить, что приложение использует OpenGL ES 2.0, и определить разрешения, необходимые для вашего приложения.
Обратите внимание, что разрешение ACCESS_FINE_LOCATION требуется только для этой демонстрации, чтобы получить местоположение пользователя для определения того, где карта должна первоначально отображаться. Если у вас есть известное местоположение в вашем собственном приложении, нет необходимости использовать местоположение пользователя.
|
1
2
3
4
5
6
|
<uses-feature
android:glEsVersion=»0x00020000″
android:required=»true»/>
<uses-permission android:name=»android.permission.INTERNET» />
<uses-permission android:name=»android.permission.ACCESS_FINE_LOCATION» />
|
В узле application вам нужно добавить две части метаданных. Первый информирует приложение об использовании сервисов Play, а второй связывает ключ API Карт с вашим приложением. В следующем фрагменте кода @string/google_api_key — это строковая ссылка на ключ из консоли разработчика Google.
|
1
2
3
4
5
6
7
|
<meta-data
android:name=»com.google.android.gms.version»
android:value=»@integer/google_play_services_version» />
<meta-data
android:name=»com.google.android.geo.API_KEY»
android:value=»@string/google_api_key»/>
|
Как только вы закончите обновление AndroidManifest.xml , закройте файл. Затем вам нужно создать новый класс Java с именем MapFragment , который расширяет SupportMapFragment . SupportMapFragment используется здесь, а не com.google.android.gms.maps.MapFragment , чтобы добавить обратную совместимость перед API 12.
Если ваше приложение не нуждается в поддержке устройств, работающих под управлением более старых версий Android, тогда лучше использовать com.google.android.gms.maps.MapFragment . После создания базового фрагмента вам необходимо реализовать шесть интерфейсов, которые мы будем использовать для этой демонстрации.
|
1
2
3
4
5
6
|
public class MapFragment extends SupportMapFragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
GoogleMap.OnInfoWindowClickListener,
GoogleMap.OnMapLongClickListener,
GoogleMap.OnMapClickListener,
GoogleMap.OnMarkerClickListener {
|
-
ConnectionCallbacksиOnConnectionFailedListenerпредназначены для мониторинга состоянияGoogleApiClient, который используется в этом приложении для получения текущего местоположения пользователя. -
OnInfoWindowClickListenerзапускается, когда пользователь нажимает на информационное окно, которое всплывает над маркером на карте. -
OnMapLongClickListenerиOnMapClickListenerзапускаются, когда пользователь либоOnMapClickListener, либо удерживает на части карты. -
OnMarkerClickListenerвызывается, когда пользователь нажимает на маркер на карте, которая обычно также отображает информационное окно для этого маркера.
При появлении запроса нажмите на красную лампочку, которая появляется рядом с именем класса, чтобы добавить методы, необходимые для этих интерфейсов.
После того, как вы создали начальный фрагмент, вы должны сообщить MainActivity , что он должен использовать этот фрагмент. Откройте файл activity_main.xml из папки ресурсов и измените его так, чтобы он включал фрагмент в качестве представления.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
<RelativeLayout xmlns:android=»http://schemas.android.com/apk/res/android»
xmlns:tools=»http://schemas.android.com/tools» android:layout_width=»match_parent»
android:layout_height=»match_parent»
tools:context=».MainActivity»>
<fragment
android:id=»@+id/map»
android:name=»com.tutsplus.mapsdemo.MapFragment»
android:layout_width=»match_parent»
android:layout_height=»match_parent»/>
</RelativeLayout>
|
После обновления макета активности вы сможете запустить свое приложение и просмотреть карту Земли, которая полностью уменьшена и сфокусирована на широте 0, долготе 0.

3. Инициализация карты
Шаг 1: Объявление типов карт
Возвращаясь к нашему классу MapFragment , вам нужно определить некоторые глобальные значения в верхней части класса для использования в вашем приложении.
|
1
2
3
4
5
6
7
8
9
|
private GoogleApiClient mGoogleApiClient;
private Location mCurrentLocation;
private final int[] MAP_TYPES = { GoogleMap.MAP_TYPE_SATELLITE,
GoogleMap.MAP_TYPE_NORMAL,
GoogleMap.MAP_TYPE_HYBRID,
GoogleMap.MAP_TYPE_TERRAIN,
GoogleMap.MAP_TYPE_NONE };
private int curMapTypeIndex = 0;
|
Здесь mGoogleApiClient и mCurrentLocation используются для получения местоположения пользователя для инициализации камеры карты. MAP_TYPES и curMapTypeIndex используются в примере кода для переключения между различными типами отображения карты. Каждый из типов карт служит разным целям, поэтому один или несколько типов могут подойти для ваших собственных приложений.
GoogleMap.MAP_TYPE_SATELLITE отображает спутниковую GoogleMap.MAP_TYPE_SATELLITE области без названий улиц или надписей.

GoogleMap.MAP_TYPE_NORMAL показывает общую карту с названиями улиц и метками.

GoogleMap.MAP_TYPE_HYBRID объединяет спутниковый и обычный режим, отображая спутниковые изображения области со всеми метками.

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

GoogleMap.MAP_TYPE_NONE похож на карту нормалей, но не отображает никаких меток или окраски для типа среды в области. Это позволяет отображать трафик и другие наложения на карте.

Шаг 2. Создание клиента API
Затем вам нужно создать свой GoogleApiClient и GoogleApiClient LocationServices , чтобы узнать текущее местоположение вашего пользователя. Как я упоминал ранее, если у вас есть заданное местоположение, которое вы хотите отобразить, а не фокусироваться на пользователе, вы можете пропустить, используя LocationServices .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
mGoogleApiClient = new GoogleApiClient.Builder( getActivity() )
.addConnectionCallbacks( this )
.addOnConnectionFailedListener( this )
.addApi( LocationServices.API )
.build();
initListeners();
}
|
Метод initListeners связывает интерфейсы, которые вы объявили в верхней части класса, с объектом GoogleMap связанным с SupportMapFragment . Вот как выглядит реализация:
|
1
2
3
4
5
6
|
private void initListeners() {
getMap().setOnMarkerClickListener(this);
getMap().setOnMapLongClickListener(this);
getMap().setOnInfoWindowClickListener( this );
getMap().setOnMapClickListener(this);
}
|
Возможно, вы заметили, что GoogleApiClient и слушатели созданы и связаны с onViewCreated а не с типичным onCreate . Это связано с тем, что объект GoogleMap не был инициализирован при onCreate , поэтому нам нужно дождаться полного создания представления, прежде чем пытаться вызвать getMap , чтобы избежать исключения NullPointerException .
Шаг 3: Настройка карты
Поскольку вы настроите камеру на карте после того, как местоположение пользователя будет найдено с помощью Play Services, мы будем использовать жизненный цикл Play Services для инициализации нашей карты. Вы можете подключить GoogleApiClient в onStart . Когда клиент подключился, вы можете получить последнее найденное пользователем местоположение и использовать его для наведения камеры на карту.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
public void onStop() {
super.onStop();
if( mGoogleApiClient != null && mGoogleApiClient.isConnected() ) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onConnected(Bundle bundle) {
mCurrentLocation = LocationServices
.FusedLocationApi
.getLastLocation( mGoogleApiClient );
initCamera( mCurrentLocation );
}
|
В методе initCamera вы инициализируете камеру и некоторые основные свойства карты. Вы начинаете с создания объекта CameraPosition через CameraPosition.Builder , с целью, установленной для широты и долготы вашего пользователя, и с установленным уровнем масштабирования.
Наклон и направление используются здесь в их значениях по умолчанию, чтобы показать, что они являются доступными вариантами. Если у вас есть объект CameraPosition , вы можете анимировать камеру в этой позиции с помощью CameraUpdateFactory .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
private void initCamera( Location location ) {
CameraPosition position = CameraPosition.builder()
.target( new LatLng( location.getLatitude(),
location.getLongitude() ) )
.zoom( 16f )
.bearing( 0.0f )
.tilt( 0.0f )
.build();
getMap().animateCamera( CameraUpdateFactory
.newCameraPosition( position ), null );
getMap().setMapType( MAP_TYPES[curMapTypeIndex] );
getMap().setTrafficEnabled( true );
getMap().setMyLocationEnabled( true );
getMap().getUiSettings().setZoomControlsEnabled( true );
}
|
В конце этого метода вы заметите, что последние четыре строки устанавливают некоторые свойства для карты. Вы устанавливаете тип карты, как описано ранее в этом учебном пособии, и включаете наложения потоков трафика в первых двух строках. setMyLocationEnabled добавляет кнопку в верхний правый угол MapFragment которая автоматически перемещает камеру в местоположение вашего пользователя при нажатии.
Наконец, вызов setZoomControlsEnabled добавляет кнопки « +» и « -» в нижнем правом углу, позволяя пользователю изменять уровень масштабирования карты без использования жестов. Есть еще несколько интересных вещей, которые вы можете установить с помощью UiSettings , таких как добавление компаса или отключение жестов, которые вы можете найти в справочной документации по Android .
4. Маркировка мест
Одна из наиболее часто используемых функций карты включает в себя указание мест с маркерами. Поскольку для добавления маркера требуются широта и долгота, вам нужно использовать OnMapClickListener чтобы позволить пользователю выбрать точку на карте для размещения объекта Marker .
|
1
2
3
4
5
6
7
8
9
|
@Override
public void onMapClick(LatLng latLng) {
MarkerOptions options = new MarkerOptions().position( latLng );
options.title( getAddressFromLatLng( latLng ) );
options.icon( BitmapDescriptorFactory.defaultMarker() );
getMap().addMarker( options );
}
|
Этот метод создает общий красный маркер, где пользователь нажал. Дополнительные параметры, такие как установка маркера как перетаскиваемого, могут быть установлены с MarkerOptions объекта MarkerOptions . Вы можете найти дополнительные атрибуты в официальной справочной документации по Android . Если вы хотите изменить цвет маркера, вы можете вызвать BitmapDescriptorFactory.defaultMarker при добавлении значка в MarkerOptions . Метод defaultMarker принимает значение с плавающей точкой, которое определяет оттенок. Оттенок может быть установлен вручную или как предопределенное статическое значение из BitmapDescriptorFactory . Следует отметить, что addMarker возвращает объект Marker , который можно сохранить для ручного удаления определенных маркеров, если это необходимо.

Если вы хотите избежать использования общих цветных штырьков для маркеров местоположения, вы можете установить растровое изображение в качестве значка на объекте MarkerOptions . Чтобы продемонстрировать это, вы переопределяете метод onMapLongClick чтобы он использовал значок приложения из папки ресурсов в качестве Marker когда пользователь долго нажимает на карту.
|
01
02
03
04
05
06
07
08
09
10
11
|
@Override
public void onMapLongClick(LatLng latLng) {
MarkerOptions options = new MarkerOptions().position( latLng );
options.title( getAddressFromLatLng( latLng ) );
options.icon( BitmapDescriptorFactory.fromBitmap(
BitmapFactory.decodeResource( getResources(),
R.mipmap.ic_launcher ) ) );
getMap().addMarker( options );
}
|
Вы, наверное, заметили, что метод getAddressFromLatLng используется в обоих методах click. Это вспомогательный метод, который берет LatLng и запускает его через Geocoder для получения адреса улицы. В последних двух примерах мы используем этот метод для отображения адреса улицы при касании маркера.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
private String getAddressFromLatLng( LatLng latLng ) {
Geocoder geocoder = new Geocoder( getActivity() );
String address = «»;
try {
address = geocoder
.getFromLocation( latLng.latitude, latLng.longitude, 1 )
.get( 0 ).getAddressLine( 0 );
} catch (IOException e ) {
}
return address;
}
@Override
public boolean onMarkerClick(Marker marker) {
marker.showInfoWindow();
return true;
}
|

5. Рисование на карте
У объекта GoogleMap есть набор методов, которые позволяют легко рисовать фигуры и размещать изображения на карте. Чтобы нарисовать простой круг, вам нужно всего лишь создать объект CircleOptions , установить радиус и расположение центра, а также определить цвет и размер обводки / заливки.
Если у вас есть объект CircleOptions , вы можете вызвать addCircle чтобы нарисовать определенный круг поверх карты. Как и при размещении маркеров, объекты, нарисованные на карте, возвращают объект типа нарисованного элемента, поэтому на него можно ссылаться позже, если это необходимо.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
private void drawCircle( LatLng location ) {
CircleOptions options = new CircleOptions();
options.center( location );
//Radius in meters
options.radius( 10 );
options.fillColor( getResources()
.getColor( R.color.fill_color ) );
options.strokeColor( getResources()
.getColor( R.color.stroke_color ) );
options.strokeWidth( 10 );
getMap().addCircle(options);
}
|

Чтобы нарисовать другую замкнутую форму, вы можете взять несколько точек LatLng и создать объект PolygonOptions . Как вы можете видеть ниже, PolygonOptions создаются аналогично CircleOptions . Вместо того, чтобы использовать метод center и radius , вы используете add со списком точек. Затем вы можете вызвать addPolygon чтобы нарисовать форму. Для этого примера вы просто рисуете треугольник на карте.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
private void drawPolygon( LatLng startingLocation ) {
LatLng point2 = new LatLng( startingLocation.latitude + .001,
startingLocation.longitude );
LatLng point3 = new LatLng( startingLocation.latitude,
startingLocation.longitude + .001 );
PolygonOptions options = new PolygonOptions();
options.add( startingLocation, point2, point3 );
options.fillColor( getResources()
.getColor( R.color.fill_color ) );
options.strokeColor( getResources()
.getColor( R.color.stroke_color ) );
options.strokeWidth( 10 );
getMap().addPolygon( options );
}
|

Последний тип рисования, о котором вы узнаете, — это добавление изображения в качестве наложения на карту. Наложения могут быть полезны, если у вас есть нарисованная карта для области, которую вы хотите отобразить поверх обычного типа карты. Это может быть достигнуто путем создания GroundOverlayOptions с заданным местоположением, шириной и высотой и изображением, которое вы хотите использовать в качестве BitmapDescriptor .
В следующем методе вы рисуете значок запуска для приложения как наложение на плитки карты.
|
01
02
03
04
05
06
07
08
09
10
|
private void drawOverlay( LatLng location, int width, int height ) {
GroundOverlayOptions options = new GroundOverlayOptions();
options.position( location, width, height );
options.image( BitmapDescriptorFactory
.fromBitmap( BitmapFactory
.decodeResource( getResources(),
R.mipmap.ic_launcher ) ) );
getMap().addGroundOverlay( options );
}
|
Вывод
Из этого руководства вы узнали, как создать ключ API и включить Google Maps для Android. Вы также узнали о классе MapFragment и некоторых основных функциях, которые можно активировать для карты.
Вы узнали, как размещать маркеры, прислушиваться к взаимодействию с картой и рисовать на карте для отображения дополнительной информации.
В следующем уроке из этой серии вы узнаете, как наложить View на MapFragment , как взаимодействовать с картами уровней внутри помещений и как показать вид улиц своим пользователям.