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