HERE Android SDK Developer's Guide

3D Venues FAQ

Can I customize the venue color scheme and venue icon?

Yes. Venue attributes can be customized using the StyleSettings object.

There are two types of icons:
  • Icons displayed on the map for a space, point-space, or facility (SVG file format)
  • Icons displayed in native controls, such as a search filter list (PNG file format)

Map icons can be customized in two ways, either by replacing the respective SVG asset files with customized ones, or by dynamically replacing it at runtime using the StyleSettings object. See the following code snippet as an example on how to customize icon for a space.

@Override
public void onVenueSelected(Venue venue) {
  if (venue.getId().equals("DM_12468")) {
    Space t1Space = venue.getSpace("Lv26051Ds3186063");
    if (t1Space != null) {
      VenueController venueCtlr = m_venueLayer.getVenueController(venue);
      Bitmap bitmap =  BitmapFactory.decodeResource(m_venueLayer.getActivity().getResources(),
        R.drawable.ic_terminal_c);
      Image image = new Image();
      image.setBitmap(bitmap);
      StyleSettings settings = new StyleSettings();
      settings.setLabelImage(image);
      venueCtlr.setStyleSettings(settings, t1Space);
    }
  }
}
Note: Using a private HERE account, PNG icons that are displayed in native controls can also be customized by replacing the respective PNG icon files with customized ones. Note that there are 4 different sizes for each Android resolution type. To make these customizations, contact a HERE representative.

Can logos be added for individual spaces, such as for a restaurant?

Yes. You can modify the icon for an individual space dynamically using the StyleSettings object. For details, see the StyleSettings API Reference.

Is it possible to expose venue data, in a classified manner, for a single user?

Yes, you can create a private HERE account and expose a "customized" version of the venue to it. Please contact a HERE representative for more information.

What fonts are supported by the Venues feature?

There is currently no support for fonts. Only the default font is supported.

Are there venue routing penalties for different types of connectors, such as elevators?

Penalties are applied when the route is calculated in "fastest" mode. For "shortest" mode, connectors are considered only if the geometry has a significant distance.

How can I create a colored MapMarker?

See the following code snippet or the MapMarker API Reference .

MapMarker m_marker;

    @Override
    public void onSpaceSelected(Venue venue, Space space) {
        removeMarker();
        Bitmap bitmap =  BitmapFactory.decodeResource(getResources(), R.drawable.pin_start);
        Image image = new Image();
        image.setBitmap(bitmap);
        m_marker = new MapMarker(space.getCenter(), image);
        m_marker.setAnchorPoint(new PointF(image.getWidth() / 2f, 0.9f * image.getHeight()));
        m_marker.setOverlayType(MapOverlayType.FOREGROUND_OVERLAY);
        m_marker.setZIndex(100);
        getMap().addMapObject(m_marker);
    }
 
    @Override
    public void onSpaceDeselected(Venue venue, Space space) {
        removeMarker();
    }
 
    private void removeMarker() {
        if (m_marker != null) {
            getMap().removeMapObject(m_marker);
            m_marker = null;
        }
    }

How do I select point-spaces (spaces without geometry) and calculate a route to such a position?

Take the tapped position and calculate the route from those coordinates. The following is an example of how to handle the map tap events to get a location for a route.

public boolean onMapTapped(PointF point) {
  Map map = m_venueLayer.getMap();
  GeoCoordinate tapPoint = map.pixelToGeo(point);
  if (tapPoint == null || !tapPoint.isValid()) {
    return false;
  }

  Venue venue = m_venueLayer.getSelectedVenue();
  VenueController venueController = null;
  if (venue != null) {
    venueController = m_venueLayer.getVenueController(venue);
  }

  if (venueController == null) {
    // null controller means that there is no venue open in 3d mode,
    // so use the tap point as outdoor location
    BaseLocation location = new OutdoorLocation(tapPoint);
    addRoutePoint(location);
    return false;
  }

  // if the controller is not null, get the tapped point as a location inside venue
  BaseLocation location = venueController.getLocation(point, m_preferSpaceSelection);
  addRoutePoint(location);

  return false;
}

private void addRoutePoint(BaseLocation location) {
  //Logic for saving route points.
}

How do I calculate the length of a route?

  1. From the CombinedRoute result object, get all the route sections. Route sections can be of three types: VENUE, LINK, or OUTDOOR.
  2. For each route type, you need to calculate its distance individually. See the following example on how to calculate length of different route types.

private void calculateLength(CombinedRoute combinedRoute) {

  List<IRouteSection> sections = combinedRoute.getRouteSections();
  double distance = 0.0;
  for (IRouteSection section : sections) {
    if (section instanceof VenueRoute) {
      // get length of indoor sections
      List<VenueManeuver> maneuvers = ((VenueRoute)section).getVenueManeuvers();
      distance += (double)maneuvers.get(maneuvers.size() - 1).getDistanceFromStart();
    } else if (section instanceof LinkingRoute) {
      // get length of link sections
      distance +=
        ((LinkingRoute)section).getFrom().distanceTo(((LinkingRoute) section).getTo());
    } else if (section instanceof OutdoorRoute) {
      // get length of outdoor sections
      com.here.android.mpa.routing.Route route = ((OutdoorRoute)section).getRoute();
      distance += (double)route.getLength();
    }
  }
}

How can my app automatically open a venue right after the app starts?

At app start, make sure the VenueService is initialized and then select the desired venue using VenueMapFragment, as shown in the following example:

//1. make sure VenueService is initialized
if (VenueMapFragment.getVenueService().getInitStatus()  == ONLINE_SUCCESS ||
  VenueMapFragment.getVenueService().getInitStatus()  == OFFLINE_SUCCESS) {
//2. Then, use the method to get the desired venue
  VenueMapFragment.selectVenueAsync(String id);
}

How can my app detect whether a route passes a specific type of space, such as a security gate?

To identify if a route passes a certain type or category of space, loop through the route sections and inspect if a maneuver contains a space in the expected category. For example, the following code snippet shows how to find the first venue maneuver with category 4, which represents a security gate.

private void findSecurityGate(CombinedRoute route) {
  for (IRouteSection section: route.getRouteSections()) {
    if (section.getRouteSectionType() == IRouteSection.RouteSectionType.VENUE) {
      VenueRoute venueRoute = (VenueRoute) section;
      List<VenueManeuver> maneuvers = venueRoute.getVenueManeuvers();
      for (VenueManeuver maneuver: maneuvers) {
        if (maneuver.getSpace() != null && maneuver.getSpace().getContent() != null) {
          Content content = maneuver.getSpace().getContent();
          if (content.getCategoryId().equals("4")) {
            // create alert;
            return;
          }
        }
      }
    }
  }
}

We get the spaces and facilities by iterating through all the levels and calling the getSortedSpacesWithFacilities() method. Is it possible to also get the entrances?

This is the correct way to get a list with all the spaces and facilities. However, entrances (accessors) are not exposed as POIs at the moment.

Is there a way to only show the venue model without showing the map tiles beneath it?

At the moment, a venue can only be shown on top of the map.

Is there a way to integrate 3D Venues with Apache Cordova?

We do not support a Cordova plug-in. Only native Android and iOS SDKs are supported.

Can airport venues be identified by their IATA airport codes?

This can only be done by searching through the core map POI database (for example, using HERE WeGo app) for the IATA code. For example, you may search for "fra", "Fra", or "FRA" and get the POI result "Frankfurt Airport (FRA)". By doing this, the venue map model's footprint (DM_9964 - "Frankfurt International Airport") becomes exposed on the map as an unopened model within the map bounding box.

How can I get a nearby space based on a location and a radius?

This is not currently supported.

How can I get a nearby space based on an indoor routing line?

This is not possible at the moment. This is planned for a future release.

How can I get a certain area around a venue model for offline mode?

Once a venue has been downloaded, it is cached and be available later in offline mode. However, you need to be online and request the venue prior to this.

Can venue entrance markers be customized ?

HERE SDK already marks entrances on the map and on the route with entrance icons. For private venues, these icons can be customized by contacting HERE representatives.

How do I pre-cache known airports without user interaction?

You need to download venues using VenueService.
  • v.getVenueAsync()
  • v.getVenueAt()
  • v.getVenueById()
  • v.getVenuesIn()
For more information, see the VenueService API Reference .

How do I translate geo-locations into indoor locations, expressed as latitude, longitude, and level, for a given functional call within the HERE SDK?

You need to have the geo-location which you want to map inside the venue, as well as the level on which you intend to place those coordinates. Thus, you can use LevelLocation to construct the indoor location.

GeoCoordinate m_currentPosition;
String m_buildingId;
Integer m_levelId;
Level m_currentLevel;
LevelLocation m_levelLocation;
OutdoorLocation m_outdoorLocation;

@Override
public void onPositionUpdated(LocationMethod locationMethod, GeoPosition currentPosition,
    boolean isMapMatched) {

  // Get position in GeoCoordinates
  m_currentPosition = currentPosition.getCoordinate();
  m_map.setZoomLevel(17.0);
  m_map.setCenter(m_currentPosition, Animation.NONE);
  if (currentPosition.getBuildingId() != null) {
    // If inside a venue get building information and initiate venue opening
    // Get buidling id (venue id)
    m_buildingId = currentPosition.getBuildingId();
    // Get level number
    m_levelId = currentPosition.getFloorId();
    // Get 3d venue based on venue id.
    // Venue object is available as parameter of onVenueSelected callback of VenueListener.
    // In order to get that callback, register your application to receive this
    // callback with VenueService.addVenueLoadListener method.
    if (m_venueLayer.getSelectedVenue() == null ||
      (!m_venueLayer.getSelectedVenue().getId().equals(m_buildingId)))
    {
      m_venueLayer.selectVenueAsync(m_buildingId);
    }
  } else {
    // In not inside a venue create an outdoor location
    m_outdoorLocation = new OutdoorLocation(m_currentPosition);
  }
}

@Override
public void onVenueSelected(Venue venue) {
  // Get Level object based on level id.
  // Java 8 offers more elegant way to iterate using filter but assume we need to stick on Java 7
  List<Level> levels = venue.getLevels();
  boolean found = false;
  for (int i = 0; i < levels.size() && !found; ++i ) {
    if (levels.get(i).getFloorNumber() == m_levelId) {
      m_currentLevel = levels.get(i);
      found = true;
    }
  }
  // Create LevelLocation object
  m_levelLocation =
    new LevelLocation(m_currentLevel, m_currentPosition, m_venueLayer.getVenueController(venue));
}