Статьи

Добавьте элегантные карты в ваше приложение для Android с помощью MapBox

Mapbox — это SDK с открытым исходным кодом для идеальных по пикселям векторных карт, который обещает скорость рендеринга и плавность видеоигры. Если вы заинтересованы в интеграции функциональности карты в свои приложения, тогда стоит рассмотреть Mapbox.

Обзор и примеры Mapbox Android SDK являются хорошей отправной точкой. В этом уроке я создам что-то более сложное, приложение, которое рисует лучший маршрут от пункта отправления до пункта назначения на карте.

Последний проект

Давайте начнем!

Вы можете найти код для окончательного проекта на GitHub .

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

Токен Mapbox

Добавьте токен в strings.xml в вашем проекте Android:

<string name="accessToken">Your access token</string> 

В AndroidManifest.xml добавьте следующие разрешения для доступа в Интернет и определения местоположения.

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 

Примечание . В Android Marshmallow (API 23) и выше необходимо запрашивать разрешения во время выполнения .

Установка Mapbox

Откройте build.gradle (Module: app) и добавьте MapBox в качестве зависимости.

 repositories { mavenCentral() } dependencies { . . . compile('com.mapbox.mapboxsdk:mapbox-android-sdk:3.2.0@aar') { transitive = true } compile ('com.mapbox.mapboxsdk:mapbox-android-directions:1.0.0@aar'){ transitive=true } } 

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

Макет карты

В файле макета content_main.xml замените содержимое следующим:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:mapbox="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.valdio.mapboxintegration.MainActivity" tools:showIn="@layout/activity_main"> <com.mapbox.mapboxsdk.views.MapView android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" mapbox:access_token="@string/accessToken" /> </RelativeLayout> 

Инициализируйте переменные, которые вам понадобятся в классе MainActivity :

 public class MainActivity extends AppCompatActivity { private MapView mapView = null; private String MAPBOX_ACCESS_TOKEN = ""; private DirectionsRoute currentRoute = null; ... 

В onCreate() файла MainActivity.java удалите панель инструментов и код кнопки плавающего действия и инициализируйте карту, добавив:

 String MAPBOX_ACCESS_TOKEN = getResources().getString(R.string.accessToken); // Set up a standard Mapbox map MapView mapView = (MapView) findViewById(R.id.mapview); mapView.setAccessToken(MAPBOX_ACCESS_TOKEN); mapView.setStyleUrl(Style.MAPBOX_STREETS); // specify the map style mapView.setZoom(14); // zoom level mapView.onCreate(savedInstanceState); 

Карты Mapbox должны реализовывать методы жизненного цикла Activity чтобы избежать ошибок времени выполнения, поэтому добавьте необходимые функции переопределения.

 @Override protected void onStart() { super.onStart(); mapView.onStart(); } @Override protected void onStop() { super.onStop(); mapView.onStop(); } @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); } @Override protected void onResume() { super.onResume(); mapView.onResume(); } @Override protected void onPause() { super.onPause(); mapView.onPause(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } 

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

Добавление маркера на карту

Добавьте следующее в onCreate в MainActivity :

 CameraPosition cameraPosition = new CameraPosition.Builder() .target(new LatLng(41.327752, 19.818666)) // Sets the center of the map to the specified location .zoom(13) // Sets the zoom level .build(); //set the user's viewpoint as specified in the cameraPosition object mapView.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); //Add a marker to the map in the specified location mapView.addMarker(new MarkerOptions() .position(new LatLng(41.327752, 19.818666)) .title("MapBox Marker!") .snippet("Welcome to my marker.")); 

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

Вот как выглядит маркер на карте:

Пример маркера

Получить местоположение устройства.

Чтобы Mapbox мог получить доступ к местоположению устройства, службы определения местоположения должны быть включены, и приложение должно иметь разрешение на их использование. Как упоминалось ранее, в Android Marshmallow (API 23) и более поздних версиях необходимо запрашивать разрешения во время выполнения .

Добавьте код, чтобы получить текущее местоположение для новой функции:

  private void myLocation() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } mapView.setMyLocationEnabled(true); mapView.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW); mapView.getMyLocation(); } 

И вызвать эту функцию после кода инициализации карты:

 ... mapView.onCreate(savedInstanceState); myLocation(); 

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

Отслеживание местоположения

Почти готово!

Теперь у вас есть маркер и местоположение, затем рисует маршрут на карте.

При этом используется вторая библиотека, импортированная в зависимостях, «Библиотека направлений», также созданная командой Mapbox.

Вот как это работает:

  1. Создайте две Waypoint , источник и пункт назначения.
  2. Создайте MapboxDirections построителя MapboxDirections , который представляет собой сетевой запрос к API-интерфейсу Mapbox, содержащий исходную и конечную Waypoint и профиль маршрута (вождение, ходьба или езда на велосипеде).
  3. Выполнить запрос направления асинхронно. Класс MapboxDirections имеет встроенный асинхронный запрос с использованием Retrofit API, используя enqueue() для выполнения запроса.
  4. Метод onResponse() возвращает ответ Retrofit, который является стандартным ответом JSON API.
  5. Тело ответа содержит пары координат местоположения, координаты, которые будут нарисованы на карте.
  6. С помощью Mapbox Polyline координаты нарисованы на карте. Полилиния — это геометрический объект с незамкнутым списком координат, нарисованным в виде линии.

Чтобы использовать библиотеку «Направление», получите местоположение устройства в качестве начальной точки и местоположение, указанное пользователем, для чего нажмите и удерживайте нажатой карту на карте в качестве конечной точки.

Создайте две точки маршрута и добавьте маркер в пункте назначения.

Добавьте следующее в onCreate функции onCreate :

 mapView.setOnMapLongClickListener(new MapView.OnMapLongClickListener() { @Override public void onMapLongClick(LatLng point) { //Remove previously added markers //Marker is an annotation that shows an icon image at a geographical location //so all markers can be removed with the removeAllAnnotations() method. mapView.removeAllAnnotations(); // Set the origin waypoint to the devices location Waypoint origin = new Waypoint(mapView.getMyLocation().getLongitude(), mapView.getMyLocation().getLatitude()); // Set the destination waypoint to the location point long clicked by the user Waypoint destination = new Waypoint(point.getLongitude(), point.getLatitude()); // Add marker to the destination waypoint mapView.addMarker(new MarkerOptions() .position(new LatLng(point)) .title("Destination Marker") .snippet("My destination")); // Get route from API getRoute(origin, destination); } }); 

Создайте сетевой запрос MapboxDirections и выполните его асинхронно.

Добавьте следующий метод, чтобы получить лучший маршрут:

 private void getRoute(Waypoint origin, Waypoint destination) { MapboxDirections directions = new MapboxDirections.Builder() .setAccessToken(MAPBOX_ACCESS_TOKEN) .setOrigin(origin) .setDestination(destination) .setProfile(DirectionsCriteria.PROFILE_WALKING) .build(); directions.enqueue(new Callback<DirectionsResponse>() { @Override public void onResponse(Response<DirectionsResponse> response, Retrofit retrofit) { // Display some info about the route currentRoute = response.body().getRoutes().get(0); showToastMessage(String.format("You are %d meters \nfrom your destination", currentRoute.getDistance())); // Draw the route on the map drawRoute(currentRoute); } @Override public void onFailure(Throwable t) { showToastMessage("Error: " + t.getMessage()); } }); } 

Нарисуйте ломаную линию на основе координат на карте.

Добавьте этот метод, чтобы нарисовать маршрут:

 private void drawRoute(DirectionsRoute route) { // Convert List<Waypoint> into LatLng[] List<Waypoint> waypoints = route.getGeometry().getWaypoints(); LatLng[] point = new LatLng[waypoints.size()]; for (int i = 0; i < waypoints.size(); i++) { point[i] = new LatLng( waypoints.get(i).getLatitude(), waypoints.get(i).getLongitude()); } // Draw Points on MapView mapView.addPolyline(new PolylineOptions() .add(point) .color(Color.parseColor("#38afea")) .width(5)); } private void showToastMessage(String message) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } 

Запустите проект, выберите две точки, и вы должны увидеть что-то вроде ниже.

Финальное приложение, показывающее маршрут

Пройдя лишнюю милю

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

Другая библиотека, которую я рекомендую, — это библиотека геокодирования для преобразования координат в адреса или наоборот. Чтобы узнать больше о MapBox, проверьте его мобильные карты , где вы можете найти информацию о библиотеках, упомянутых в этом руководстве.