Pull to refresh

Карты в вашем Android-приложении

Reading time 3 min
Views 10K


Довольно часто перед разработчиком мобильного приложения возникает необходимость отобразить что либо на карте. Какие же варианты есть у разработчика?

Я рассматривал два варианта.

Вариант 1. Внешнее приложение с картой


Пожалуй, самый простой в реализации вариант. Когда нужно, вы просто открываете сторонее приложение с картой — создаете uri вида geo: широта, долгота, в параметре z можно указать масштаб (от 1 до 23):

String uri = String.format("geo:%s,%s?z=16", Double.toString(lat), Double.toString(lng));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);

При этом, если на аппарате пользователя установлено несколько приложений с картами, то пользователю будет предложено выбрать в каком приложении должна быть показана заданная точка:



Да-да. Таким способ показывается именно заданная точка, а не просто карта (хотя, Яндекс.Карты показывают просто карту и, судя по моей переписке с ними, считают, что так и надо).

Преимущества данного варианта:
  • простота реализации;
  • все возможности внешнего приложения (например, в iGo можно сразу проложить маршрут к показанной точке; карты в некоторых приложениях будут доступны офлайн).
Недостатки:
  • нет возможности вывести дополнительную информацию (как, например, на первом в этой статье скриншоте — метки, всплывающие подсказки и т.п.).

Вариант 2. Встроенная карта


Встроенная карта более сложна в реализации. Не буду останавливаться на всех деталях, основное хорошо описано в документации.

Остановлюсь лишь на некоторых тонкостях.

Maps API Key

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

// choose layout with correct API key
if (debug) {
	setContentView(R.layout.map_debug);
} else {
	setContentView(R.layout.map_release);
}

Другие варианты (в т.ч. для определения debug/release-версии сборки) можно найти тут.

Текущее положение

Для отображения текущего положения на карте необходимо написать следующее:

private MyLocationOverlay myLocationOverlay;

MapView mapView = (MapView) findViewById(R.id.mapview);

myLocationOverlay = new MyLocationOverlay(this, mapView);
myLocationOverlay.enableMyLocation();
mapView.getOverlays().add(myLocationOverlay);

Не забудьте отключить определение местоположения при остановке/закрытии activity:

myLocationOverlay.disableMyLocation();

Маркеры

На карту маркеры добавляются просто:

List<Overlay> mapOverlays;
Drawable drawable;
MapOverlay itemizedOverlay;

mapOverlays = mapView.getOverlays();
drawable = this.getResources().getDrawable(R.drawable.map_dot_green);
itemizedOverlay = new MapOverlay(drawable, mapView);
GeoPoint markerPoint = new GeoPoint(lat, lng);
OverlayItem overlayItem = new OverlayItem(markerPoint, "name", "description");
itemizedOverlay.addOverlay(overlayItem);
mapOverlays.add(itemizedOverlay);

При этом если добавить несколько маркеров, то все маркеры на одном слое будут одинаковыми. Как сделать маркеры разными (как на скриншоте выше — желтыми, красными, зелеными)? Либо создать несколько слоев, либо воспользоваться методом SetMarker:

int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(-w / 2, -h, w / 2, 0);
overlayItem.setMarker(drawable);

Без первых трех строк вместо маркера будет показана пустота.
Если не использовать отрицательные значения w и h и не делить их пополам, то у маркеров будет неправильная тень.

Преимущества и недостатки данного варианта

Преимущества:
  • возможность создавать свои слои и свои метки;
  • возможность оставить пользователя в своем приложении (добавив, например, заголовок окна).
Недостатки:
  • относительная сложность реализации;
  • нет всех возможностей сторонних приложений;
  • activity с картой запускается достаточно долго.

Заключение


В итоге, я так и не смог сделать выбор за пользователя. Потому в моем приложении поддерживаются оба варианта — в настройках пользователь может указать хочет ли он использовать внешние приложения (по умолчанию, используется встроенная карта).
Tags:
Hubs:
+47
Comments 24
Comments Comments 24

Articles