HERE Android SDK Developer's Guide

3D Venues

This section gives an overview of the classes and interfaces associated with the 3D Venues feature. Examples of available 3D venues include shopping malls and airports. This section also explores three use cases: searching for a venue, opening a venue, and getting a notification when a venue is visible in the viewport.

The classes covered in this section include:
  • VenueMapFragment
  • VenueMapView
  • VenueService
  • VenueMapFragment.VenueListener
  • VenueLayerAdapter
  • VenueService.VenueServiceListener
Note: To use this feature, your application must include the Gson library (release 2.2.4 or a compatible version) on its class path.
Figure 1. 3D venue map of a Berlin shopping center

The 3D Venues feature can be used with or without a map. To use it with a map, use the VenueMapFragment or VenueMapView. To use 3D Venues without a map, use the VenueService class.

Using VenueMapFragment

VenueMapFragment provides developers with access to all 3D venue-related features. As with MapFragment, VenueMapFragment needs to be added to the layout file of the application, for example:

<!-- Example fragment. This can be integrated and annotated like any other android
Fragment of View widget -->
<fragment
  android:id="@+id/map_fragment"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  class="com.here.android.mpa.venues3d.VenueMapFragment" />

The fragment must then be initialized in the same manner as MapFragment.

VenueListener

To receive venue-related events, implement VenueMapFragment.VenueListener and add it to the VenueMapFragment, similar to the following code example. As with a MapFragment, you can mark VenueMapFragment initialization as successfully completed by looking for the OnEngineInitListener.Error.NONE error status code.

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // Search for the VenueMapFragment
  final VenueMapFragment mapFragment = (VenueMapFragment)
  getFragmentManager().findFragmentById(R.id.mapfragment);

  // initialize the Map Fragment and
  // retrieve the map that is associated to the fragment
  mapFragment.init(new OnEngineInitListener() {
    @Override
    public void onEngineInitializationCompleted( OnEngineInitListener.Error error) {
      if (error == OnEngineInitListener.Error.NONE) {
        // add listeners
        mapFragment.addListener(myVenueListener);
        mapFragment.getVenueService().addListener(myVenueServicelistener);
        map = mapFragment.getMap();
      } else {
        System.out.println("ERROR: Cannot initialize VenueMapFragment");
      }
    }
  });
}

In this example, myVenueListener is assumed to implement VenueMapFragment.VenueListener, and myVenueServiceListener implements VenueService.VenueServiceListener. For more information about these listener classes, see VenueService and VenueServiceListener.

Using VenueMapView

VenueMapView provides developers with similar features as VenueMapFragment, but as a MapView-based class. Like MapView, VenueMapView needs to be added to the layout file of the application:

<!-- An example VenueMapView  -->
<com.here.android.mpa.venues3d.VenueMapView
  android:id="@+id/mapcanvas"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" />

The view must then be initialized in the same manner as MapView. As with a MapView, you can mark VenueMapView initialization as successfully completed by looking for the OnEngineInitListener.Error.NONE error status:

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  // Search for the VenueMapView
  final VenueMapView mVenueMapView = (VenueMapView)findViewById(R.id.venuemapview);
  // get and initialize the MapEngine and
  // assign the VenueMapView to it
  ApplicationContext context = new ApplicationContext(this);
  MapEngine.getInstance().init(context, new OnEngineInitListener() {
    @Override
    public void onEngineInitializationCompleted( OnEngineInitListener.Error error) {
      if (error == OnEngineInitListener.Error.NONE) {
        // create and assign map
        mMap = new Map();
        mVenueMapView.setMap(mMap);
        mVenueMapView.init(this, mVenueServiceListener);
        mVenueMapView.addListener(mVenueListener);
      } else {
        System.out.println("ERROR: Cannot initialize VenueMapView");
      }
    }
  });
}

Working with 3D Venue Models

Once a VenueMapFragment or VenueMapView is correctly initialized, 3D-enabled venues become visible on the map. These venues can be distinguished by their colors and icons, as in the screenshot below. This screenshot was taken from an app that uses VenueMapFragment, but the same visuals also appear on a VenueMapView.

Figure 2. A 3D venue on the Map

VenueMapFragment offers two ways to select a venue and open the indoor map view. When a user taps the venue, the onVenueTapped(VenueController, float, float) method in VenueMapFragment.VenueListener is called with a Venue object as a parameter. The venue can then be opened by giving the Venue object to selectVenue(Venue). For example:

public void onVenueTapped(Venue venue, float x, float y) {
   mapFragment.selectVenue(venue);
 }

When the venue is selected, the onVenueSelected(Venue) callback of the VenueMapFragment.VenueListener interface is called. A venue can also be selected and opened by giving its identifier by using the selectVenueAsync(String venueId) method of VenueLayerAdapter, which is implemented by VenueMapFragment. For example, a typical scenario is a venue search where a successful search results in an opened venue.

The selectVenue(Venue) method opens the venue right away in a synchronous manner by taking a downloaded Venue object as a parameter. However, the selectVenueAsync(String) and selectVenueAsync(String, String) methods may involve downloading the venue from the backend, asynchronously, while the venue is selected and opened. You can get a notification for when asynchronous loading is complete by listening to the onGetVenueCompleted(Venue) callback in VenueService.ServiceListener.

It is also possible to receive a notification when there is a venue in the viewport. You can use this callback to implement a feature, such as drawing user attention to the venue when it is visible.

The triggering area for this is a rectangle at the center of the viewport. The width of the area is two-thirds of the screen width, and the height is equal to the width. When the center point of the venue enters this triggering area, such as during map panning, onVenueVisibleInViewport(Venue, boolean) of VenueMapFragment.VenueListener is called. The boolean parameter indicates whether the venue is entering or exiting from the triggering area. Note that to get the notifications, you must first set setVenuesInViewportCallback(boolean) to true. For example:


// enabling onVenueVisibleInViewport notification
mapFragment.setVenuesInViewportCallback(true);
 //...
@Override
public void onVenueVisibleInViewport(Venue venue, boolean visible) {
  if (visible) {
    // venue entered triggering area
  } else {
    // venue disappeared from triggering area
  }
}
      
Note: This feature is not processor-intensive, as checking only occurs once as map movement stops. The notification is not sent during continuous movement, even when there is a venue in the triggering area.

To change the current floor for a given venue, retrieve a VenueController object by using the getVenueController(String venueId) method, and then call the VenueController.selectLevel(Level) method.

You can enable animations for venue selection and floor transitions by calling setFloorChangingAnimation(true) and setVenueEnteringAnimation(true).

VenueService and VenueServiceListener

In the case where you are not using a VenueMapFragment, you can use the VenueService instead. The service initialization status is provided as a parameter to the onInitializationCompleted(InitStatus) callback method in the VenueService.VenueServiceListener interface. You can also retrieve the status using the getInitStatus() method in VenueService.

boolean cacheInUse = false
//...
@Override
public void onInitializationCompleted(InitStatus result) {
  if (result == InitStatus.ONLINE_SUCCESS) {
    // init ok, online content available
  } else if (result == InitStatus.OFFLINE_SUCCESS) {
    // cached content available
    cacheInUse = true;
  } else if (result == InitStatus.ONLINE_FAILED && cacheInUse) {
    // failed to authenticate, but cached content available
  } else {
    // something else has gone wrong
  }
}

VenueService offers methods for searching and loading venues without using a map. For example, the code below retrieves the closest venue inside a given radius near a given location. The area can also be defined by GeoBoundingBox rather than a radius.

private void loadClosestVenue() {
  VenueService venueService = VenueService.getInstance(getActivity().getApplicationContext());
  GeoCoordinate myLocation = new GeoCoordinante(60.43704, 22.21710);
  float radiusInMeters = 5000.0f;
  VenueInfo closestVenue = venueService.getVenuesAt(myLocation, radiusInMeters);
  venueService.getVenueAsync(closestVenue);
}

@Override
public void onVenueLoadCompleted(Venue venue, VenueInfo venueInfo, VenueLoadStatus loadStatus) {
  // closest venue available through the venue object
}
Note: The VenueService is also invoked when VenueMapFragment is used. As such, some venue features can be used in a common manner between these classes.

Venue Objects

The following is a list of venue objects (as Java classes) in the com.here.android.mpa.venues3d package. These objects are presented here from the lowest to the highest level of conceptual detail, and each level is related in a has-a relationship. For example, each Venue object may have multiple Level member objects, which contain multiple OuterArea objects.

Java class Description
com.here.android.mpa.venues3d.Venue Represents a building which may contain one or more structures and levels.
com.here.android.mpa.venues3d.Level Represents a floor or horizontal layer within a Venue.
com.here.android.mpa.venues3d.OuterArea Represents a part of one Level, contained within one exterior wall of a structure.
com.here.android.mpa.venues3d.Space Represents a spatial area on a Level, like a store or a facility, such as an escalator. It may contain subspaces which represent the next level of detail about a space.
com.here.android.mpa.venues3d.Content Point of interest information about a spatial area within the venue.

A Venue object consists of one or more Level objects. The Level objects represents physical levels of the venue. Each Level object consist of one or more OuterArea objects. For example, a building with common ground level areas can contain two separate towers on top of that common area, and so there would be two OuterArea objects in higher levels in that venue. An OuterArea consist of one or more Space objects.

Note that both Venue and Space classes have a member Content class, which holds point-of-interest information. This allows for a venue (such as a museum) and a space (such as a shop within a shopping mall) to hold separate address and phone numbers. Your app can use methods such as getPhoneNumber(), getWebsite() and getOpeningTimes() to retrieve the relevant directory information from Content objects.

Working with Venues

Venue, OuterArea and Space objects can be interacted by the user through tapping. For an opened venue, use the VenueMapFragment.VenueListener.onVenueSelected(Venue) callback. For a selected space, use the callback VenueMapFragment.VenueListener.onSpaceSelected(Venue, Space). Selected spaces are highlighted with different color in an opened venue.

Both Venue and Space objects contain Content objects. Content encapsulates information related to the object, such as name, address, other contact information and category of the venue or space. There is also a concept of selected floor, which is the same as the visible floor. This is demonstrated in the following screenshot. Note that the floor selection widget in this screenshot is not a part of the HERE SDK.

Figure 3. Selected Space

The following example shows how to add a MapMarker to a space upon a onSpaceSelected event, and how to remove it when the space is deselected.

@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;
    }
}

Open Mode

When open mode is enabled, venues that are in the viewport are opened automatically, rather than requiring the user to click on the venue to open it. The venue closest to the center of the screen is always selected.

Open mode can be enabled on VenueMapLayer, VenueMapView, VenueMapFragment, or VenueMapAdapter.

venueMapLayer.setOpenMode(true);
boolean isOpenMode = venueMapLayer.getOpenMode();

Dynamic Styles

StyleSettings encapsulates the parameters that have an impact on the visual appearances of opened venues. You can set space names, icons, and colors by using this object. The fill and outline colors can be also set separately to selected and unselected spaces.

The following example shows how to set the name, label, fill color, and outline color to the given Space object. The code snippet does not contain completed code but assumes that variables have been initialized.

import com.here.android.mpa.common.Image;
//...
private void updateStyles(Venue venue, Space space) {

  Integer selectedColor = 0xFFFF0000; // red, format 0xAARRGGBB
  Integer unselectedColor = 0xFFFFFF00; // yellow
  Integer outlineColor = 0xFF0000FF; // blue

VenueController controller = m_venueMapFragment.getVenueController(venue);

  StyleSettings settings = new StyleSettings();

  settings.setLabelName("My Space");

  Image img = new Image();
  img.setImageResource(com.example.android.UnitTest.R.drawable.png);
  settings.setLabelImage(img);

  settings.setSelectedFillColor(selectedColor);
  settings.setFillColor(unselectedColor);
  settings.setOutlineColor(outlineColor);

  controller.setStyleSettings(settings, space);
}

Nearby Spaces

You can find all spaces in a radius around a given position by using a Level or an OuterArea object. The position needs to be given as a geocoordinate, and the radius in meters. The returned list of spaces contains all spaces that fall within or intersect the radius.

GeoCoordinate myLocation = new GeoCoordinante(60.43704, 22.21710);
List nearbySpaces = level.getNearbySpaces(myLocation, 10.0);

Area at Position

You can retrieve areas in a level by specifying a position. The area returned will either be a Space or an OuterArea. Similarly, you can also get spaces in a OuterArea.

In case of nested spaces, the innermost nested space encompassing the position is be returned.

GeoCoordinate myLocation = new GeoCoordinante(60.43704, 22.21710);
Area area = level.getAreaAtPosition(myLocation);
Space space = outerArea.getSpaceAtPosition(myLocation);

You cannot use this account to purchase a commercial plan on Developer Portal, as it is already associated to plans with different payment methods.

To purchase a commercial plan on Developer Portal, please register for or sign in with a different HERE Account.

Something took longer than expected.

The project should be available soon under your projects page.

Sorry, our services are not available in this region.

Something seems to have gone wrong. Please try again later.

We've detected that your account is set to Australian Dollars (AUD).
Unfortunately, we do not offer checkouts in AUD anymore.
You can continue using your current plan as normal, but to subscribe to one of our new plans,
please register for a new HERE account or contact us for billing questions on selfservesupport@here.com.