
Довольно часто перед разработчиком мобильного приложения возникает необходимость отобразить что либо на карте. Какие же варианты есть у разработчика?
Я рассматривал два варианта.
Вариант 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 с картой запускается достаточно долго.
Заключение
В итоге, я так и не смог сделать выбор за пользователя. Потому в моем приложении поддерживаются оба варианта — в настройках пользователь может указать хочет ли он использовать внешние приложения (по умолчанию, используется встроенная карта).