LogoLogo
CMSGitHubSupportBook a demo
  • Documentation
  • Academy
  • Help Center
  • Welcome
  • SDKS & Frameworks
    • Web
      • Getting Started
        • Prerequisites
          • MapsIndoors
          • Map Engine Provider
            • Option 1: Get your Mapbox Access Token
            • Option 2: Get your Google Maps API Keys​
          • Map Engine Setup
        • Getting Started: MapsIndoors
      • Map Visualization
        • Highlight, Hover and Select
        • Remove Labels from Buildings and Venues
        • Change Building Outline
        • Managing Collisions Based on Zoom Level
        • 3D Maps
          • Managing your 3D Maps
        • Base Map Styling - Google Maps
        • Managing feature visibility for Mapbox
      • Wayfinding
        • Directions
        • Directions Service
          • Tailoring the directions to your specific needs
        • Directions Renderer
          • Customizing the Route Animation
        • Multi-stop navigation
          • Custom Icons
        • User's Location as Point of Origin
      • Search
        • Search Operations
        • Searching
        • Using External ID, Geospatial Joins
        • Utilizing MapsIndoors Web Components and Other Searches
      • Map Management
      • Data Visualization
        • Display Heatmap Overlay
      • Other guides
        • Authentication
          • Single Sign-On
            • SSO Configuration
            • SSO Authorisation
          • 2-Factor Authentication
          • Password Reset
        • Application User Roles
        • Custom Properties
        • Display Language
        • Language
        • User Positioning
          • Show User's Location aka. Blue Dot
          • Using Cisco DNA Spaces
        • Working with Events
        • Turn Off Collisions Based on Zoom Level
        • Remove Labels from Buildings and Venues for Web
        • Synchronizing data for a subset of venues
        • Custom Floor Selector
      • Display Rules in Practice
      • Offline Data
      • Managing map visibility
    • Android
      • Getting Started
        • Prerequisites
        • Create a New Project
        • Show a Map
        • Create a Search Experience
        • Getting Directions
        • Enable Live Data
        • Integrating MapsIndoors into your own App
        • Migrating from V3 to V4
          • Migrating to Mapbox V11
      • Directions
        • Directions Service
        • Directions Renderer
          • User's Location as Point of Origin
        • Wayfinding Instructions
          • See Route Element Details
        • Using multi-stop navigation
      • Searching
        • Searching on a Map
        • Creating a Search Experience
      • Switching Solutions
      • Caching & Offline Data
      • Display Language
      • Displaying Objects
        • Application User Roles
        • Getting a Polygon from a Location
        • Location Clustering
        • Location Data Sources
        • Location Details
        • Turn Off Collisions Based on Zoom Level
        • Enabling and Disabling features on the map
      • Change Building Outline Color
      • Event Logging
      • Configuring a menu with AppConfig
      • Display Heatmap Overlay
      • Custom Properties
      • Custom Floor Selector
      • External IDs
      • User Positioning
        • Show User's Location aka. Blue Dot
        • Using Cisco DNA Spaces
        • Using Google Fused Location Provider
        • Using Indoor Atlas
      • Authentication
        • Single Sign-On
          • SSO Configuration
          • SSO Authorisation
        • 2-Factor Authentication
        • Password Reset
      • Display Rules in Practice
        • Label styling through Display Rules
      • Highlight and Select
    • iOS
      • Getting Started
        • Prerequisites
        • Set Up Your Environment
        • Display a Map
        • Search
        • Getting Directions
        • Migrating from v3 to v4
      • Directions
        • Directions Renderer
          • User's Location as Point of Origin
        • Wayfinding Instructions
          • See Route Element Details
        • Directions Service
        • Using multi-stop navigation
      • Searching
        • Searching on a Map
        • Creating a Search Experience
      • Caching & Offline Data
      • Displaying Objects
        • Application User Roles
        • Getting a Polygon from a Location
        • Location Details
        • Turn Off Collisions Based on Zoom Level
        • Enabling and Disabling features on the map
      • Custom Floor Selector
      • Change Building Outline Color
      • Custom Map Padding
      • Custom Properties
      • Display Rules in Practice
        • Label styling through Display Rules
      • Switching Solutions
      • Show User's Location aka. Blue Dot
        • Using Indoor Atlas
        • Using Cisco DNA Spaces
      • Highlight and Select
      • Display Language
    • React Native
      • Getting Started
        • Prerequisites
        • Project Setup
        • Displaying a Map
        • Creating a Search Experience
        • Getting Directions
        • Enabling Live Data
      • Showing Blue Dot
    • Flutter
      • Getting Started
        • Prerequisites
        • Create a New Project
        • Show a Map
        • Create a Search Experience
        • Getting Directions
      • Migration Guide
    • Integration API
      • Integration API Access
        • Access with Swagger
        • Access with Postman
        • Access with Python
        • Client credentials flow
      • Data Description
      • Reverse Geocoding
      • Route Access
      • OpenAPI Specification
    • Built-In Map Edits
      • Getting started
      • Authentication
      • Release notes
      • Reference docs
  • Products
    • Product Overview
    • CMS
      • Interface Overview
      • Display Rules
      • Location Types
      • Categories
      • Media Library
        • 2D Models and Icons
        • 3D Models
      • Editing Data
      • Solution Settings
      • Settings
      • Data Concepts
      • User Roles
      • Route Network
        • Barrier Route Element
        • Door Route Element
      • Additional Location Details
    • Map Template
      • Getting Started
        • Web Component
        • React Component
      • Configuration
        • Query Parameters
        • Categories
      • Customization
      • Deploying Map Template to a cloud storage provider
      • 2D/3D Visibility Switch
      • External customization of the Map Template
      • Location Details configuration
      • Kiosk
        • QR code configuration
  • Other
    • Map Design
      • Map Design System
      • Using a Custom Mapbox MapStyle
      • 2D Models
    • Changelog
      • Web SDK
        • V4
        • V3
      • Android SDK
        • V4
        • V3
      • iOS SDK
        • V4
        • V3
      • React Native SDK
      • Flutter SDK
      • MI Components
      • Map Template
    • Glossary
  • Legacy Docs
    • Android SDK V3
      • Getting Started
        • Prerequisites
        • Create a New Project
        • Show a Map
        • Create a Search Experience
        • Getting Directions
        • Enable Live Data
        • Integrating MapsIndoors into your own App
    • iOS SDK V3
      • Getting Started
        • Prerequisites
        • Set Up Your Environment
        • Display a Map
        • Search
        • Directions
        • Live Data
        • Integrating MapsIndoors into your own App
      • Inspect Route Element for iOS v3
      • Using Cisco DNA Spaces
      • Using Indoor Atlas
      • Switching Solutions
      • Show User's Location aka. Blue Dot
      • Application User Roles
      • Getting a Polygon from a Location
      • Location Details
  • MapsIndoors SDK Firewall
  • Google Analytics & Logging
  • Reference Docs
    • Web SDK
    • Android SDK
    • iOS SDK
    • React Native SDK
    • Flutter SDK
Powered by GitBook
On this page
  • Live Topics​
  • Live Updates​

Was this helpful?

Export as PDF
  1. SDKS & Frameworks
  2. Android

Live Data

Last updated 1 year ago

Was this helpful?

This guide gives an overview of how to work with Live Data in the MapsIndoors Android SDK. As opposed to static data, which does not change unless data is synchronized, Live Data can change in real time, and these changes can be instantly reflected on the map and in searches.

Common use-cases are:

  • Changing the appearance of meeting rooms or workspace desks on a map, or in a list, based on occupancy information. For example, change the icon in order to indicate that a room is occupied.

  • Changing the position of a POI representing a vehicle.

Support for Live Data requires that server-side integrations are in place. For example, visualizing live occupancy data requires that a calendar or booking system integration is in place. An integration like that is set up in .

Live Topics

All Live Data is ordered in so-called Topics. A MapsIndoors Topic is hierarchical in the way it is defined, and its relation to MapsIndoors data is derivable by its 7 components:

  1. Dataset

  2. Venue

  3. Building

  4. Floor

  5. Room

  6. Location

  7. Domain Type

As a minimum, all Topics relate to a Data Set (also known as a "Solution" in MapsIndoors), a Domain Type and one (or more) of the other components.

Domain Type

The Domain Type describes what kind of conceptual Domain the Live Data belongs to. Here are some examples of Domain Types:

  • Availability - The current availability state of a particular bookable room or workspace

  • Occupancy - The current known occupancy of a given capacity, for example in a meeting room

  • Position - The current geo-spatial position and related floor

The Domain Type is not bound to be one of the above, but could be very specific to a particular use-case, source of data and technical integration.

Knowing that updates are ordered in Topics, it is possible to subscribe to updates using a Topic Criteria. Filtering out live updates can be done on all levels of the Topic Criteria. For example, you might want to subscribe to all position updates but only for a particular Floor in a particular Building. This can be done by setting the correct IDs on the Floor and Building component. Leaving out a component means that we will get all updates, regardless of what relation the updates have at that level. Continuing the example, leaving out the Floor component means that we get all position updates on all Floors, but still only for a particular Building.

A live update is the model for a message carrying one piece of Live Data, for example that a particular room is now occupied. It contains the Topic for the live update and the actual live properties as a dictionary of strings.

Enabling Live Data through the MapControl is an easy way to get Live Data running in your app.

mMapControl.enableLiveData(LiveDataDomainTypes.OCCUPANCY_DOMAIN)
mMapControl.enableLiveData(LiveDataDomainTypes.AVAILABILITY_DOMAIN)

In the example we enable Live Data for the "Availability" and "Occupancy" Domain types. Internal processes will determine which Topics are relevant for subscription based on where the map is situated. A default rendering mechanism will also alter the appearance of the relevant Locations on the map. As a consequence, the SDK will set custom Display Rules for this rendering. Adding your own, or resetting Display Rules, while Live Data is enabled with default rendering, may break the rendering for the current MapControl instance. Hence, you should not use custom Display Rules unless you are handling the rendering of Live Data on your own.

You can disable the Live Data again by calling disableLiveData(String domainType).

Note that using the enableLiveData methods on MapControl has some limitations, and is thereby not suitable for all use cases.

  • Since MapControl will try to determine the Live Data subscriptions based on where the map is currently situated, it might not detect Live Data updates of the position Domain representing moving objects entering the visible region of the map.

  • Since MapControl does not know which Live Updates are relevant to show, it will need to subscribe to all Live Data in the visible region, which, depending on your amount of Live Data, may or may not lead to app performance implications.

To enable Live Data in an application, a subscription to one or more Topics is needed. Once subscribed, the application can be notified about changes and decide what to do. The application is in control of what should happen upon receiving live data updates, and the MapsIndoors SDKs provide mechanisms to efficiently make updates to the map representation of Locations. The central class to carry out these tasks is the LiveDataManager.

The only Live Data updates that are also directly notified to the SDK internally are Live Data updates of the "Position" Domain Type. By consequence, if you have already set up your map with MapsIndoors, an additional few lines of code can enable moving locations on the map. Here is an example in Java:

var liveDataManager = LiveDataManager.getInstance();
liveDataManager.setOnLiveDataManagerStateChangedListener {
    Log.d("LiveDataState", "Live Data manager state changed to: $it")
}
var liveTopicCriteria = LiveTopicCriteria.getBuilder("datasetId")
    .setMultiLevelWildcard()
    .build();
liveDataManager.subscribeTopic(liveTopicCriteria);

In the example, the Topic is created using the datasetId and a multilevel wildcard, which will return all Live Data in the Solution.

As mentioned MapControl has a default way of rendering Live Data Locations if you call enableLiveData(String domainType). If you need to show Live Data in another way, you can add handlers for this, either through setOnWillUpdateLocationsOnMap(OnWillUpdateLocationsOnMap listener) or by calling enableLiveData(String domainType, OnLiveLocationUpdateListener OnLiveLocationUpdateListener).

Here are examples of using the different methods to render Live Data on your map:

mMapControl.setOnWillUpdateLocationsOnMap { locations: List<MPLocation> ->
    for (location in locations) {
        val occupancy = location.getLiveUpdate("occupancy")
        val currentDisplayRule = mMapControl.getDisplayRule(location)
        val displayRuleName = location.id + "_live"
        if (occupancy != null) {
            val occupancyProperty = occupancy.occupancyProperties
            val occupancyDisplayRule =
                LocationDisplayRule.Builder(displayRuleName, currentDisplayRule!!)
                    .setLabel("people = " + occupancyProperty.nrOfPeople)
                    .build()
            mMapControl.setDisplayRule(occupancyDisplayRule, location)
        }
    }
}
mMapControl.enableLiveData(LiveDataDomainTypes.OCCUPANCY_DOMAIN) { location: MPLocation ->
    val occupancy = location.getLiveUpdate("occupancy")
    val currentDisplayRule = mMapControl.getDisplayRule(location)
    val displayRuleName = location.id + "_live"
    if (occupancy != null) {
        val occupancyProperty = occupancy.occupancyProperties
        val occupancyDisplayRule =
            LocationDisplayRule.Builder(displayRuleName, currentDisplayRule!!)
                .setLabel("people = " + occupancyProperty.nrOfPeople)
                .build()
        mMapControl.setDisplayRule(occupancyDisplayRule, location)
    }
}

Note that since there is no guarantee of which Live Data you receive first, and Locations can have multiple Live Data updates on different domains, we recommend checking the lastModifiedTimeStamp of each Live Data update to select which one to render.

While only a few lines of code can get things moving around on a map, there are of course more handles that are relevant to create a robust and user-friendly real-time map experience.

There are two ways to be notified about Live Updates:

  1. On a general level through OnReceivedLiveUpdateListener, which is suitable in scenarios where all Live Updates might potentially affect the end user's decisions, for example when searching broadly for an available meeting room.

  2. On a map-specific level through MapControl, which is suitable in scenarios where the map is the context for the user's actions, for example when browsing the map for an available meeting room nearby

To get Live Updates on a general level the OnReceivedLiveUpdateListener must be set on the LiveDataManager:

liveDataManager.setOnReceivedLiveUpdateListener { liveTopic, liveUpdate ->
            if (liveUpdate.domainType == LiveDataDomainTypes.OCCUPANCY_DOMAIN) {
                var people = liveUpdate.occupancyProperties.nrOfPeople
                ...
            }
        }

To get Live Updates on a map-specific level, the OnWillUpdateLocationsOnMap must be set on MapControl:

mMapControl.setOnWillUpdateLocationsOnMap { locations ->
            for (location in locations) {
                val properties = location.getLiveUpdate(LiveDataDomainTypes.OCCUPANCY_DOMAIN)?.occupancyProperties
                ...
            }
        }

In order to get notified about state changes and errors related to Live Data, a number of listeners can be set on the LiveDataManager using the following methods and interfaces:

  • setOnReceivedLiveUpdateListener(OnReceivedLiveUpdateListener listener);

  • setOnTopicSubscribedListener(OnTopicSubscribedListener listener);

  • setOnTopicSubscribeErrorListener(OnTopicSubscribeErrorListener listener);

  • setOnTopicUnsubscribedListener(OnTopicUnsubscribedListener listener);

  • setOnTopicUnsubscribeErrorListener(OnTopicUnsubscribeErrorListener listener);

  • setOnLiveDataManagerStateChangedListener(OnLiveDataManagerStateChangedListener listener);

  • setOnErrorListener(OnErrorListener listener);

Live Updates are dependent on network connectivity, so the Live Data Manager will try to recover from common errors like e.g. a network dropout. The Live Data Manager will not try to recover from subscription errors alone, as this could be caused by a non-existing Topic for a given Dataset, thus it does not make sense retrying the failing subscription.

Enabling Live Data through the MapControl is an easy way to get Live Data running in your app.

mapControl.enableLiveData(LiveDataDomainTypes.OCCUPANCY_DOMAIN);
mapControl.enableLiveData(LiveDataDomainTypes.AVAILABILITY_DOMAIN);

In the example we enable Live Data for the "Availability" and "Occupancy" Domain types. Internal processes will determine which Topics are relevant for subscription based on where the map is situated. A default rendering mechanism will also alter the appearance of the relevant Locations on the map. As a consequence, the SDK will set custom Display Rules for this rendering. Adding your own, or resetting Display Rules, while Live Data is enabled with default rendering, may break the rendering for the current MapControl instance. Hence, you should not use custom Display Rules unless you are handling the rendering of Live Data on your own.

You can disable the Live Data again by calling disableLiveData(String domainType).

Note that using the enableLiveData methods on MapControl has some limitations, and is thereby not suitable for all use cases.

  • Since MapControl will try to determine the Live Data subscriptions based on where the map is currently situated, it might not detect Live Data updates of the position Domain representing moving objects entering the visible region of the map.

  • Since MapControl does not know which Live Updates are relevant to show, it will need to subscribe to all Live Data in the visible region, which, depending on your amount of Live Data, may or may not lead to app performance implications.

To enable Live Data in an application, a subscription to one or more Topics is needed. Once subscribed, the application can be notified about changes and decide what to do. The application is in control of what should happen upon receiving live data updates, and the MapsIndoors SDKs provide mechanisms to efficiently make updates to the map representation of Locations. The central class to carry out these tasks is the LiveDataManager.

The only Live Data updates that are also directly notified to the SDK internally are Live Data updates of the "Position" Domain Type. By consequence, if you have already set up your map with MapsIndoors, an additional few lines of code can enable moving locations on the map. Here is an example in Java:

LiveDataManager liveDataManager = LiveDataManager.getInstance();
liveDataManager.setOnLiveDataManagerStateChangedListener(state -> Log.d(TAG,"Live Data manager state changed to: "+state.toString()));
LiveTopicCriteria liveTopicCriteria = LiveTopicCriteria.getBuilder("datasetId")
        .setMultiLevelWildcard()
        .build();
liveDataManager.subscribeTopic(liveTopicCriteria);

In the example, the Topic is created using the datasetId and a multilevel wildcard, which will return all Live Data in the Solution.

As mentioned MapControl has a default way of rendering Live Data Locations if you call enableLiveData(String domainType). If you need to show Live Data in another way, you can add handlers for this, either through setOnWillUpdateLocationsOnMap(OnWillUpdateLocationsOnMap listener) or by calling enableLiveData(String domainType, OnLiveLocationUpdateListener OnLiveLocationUpdateListener).

Here are examples of using the different methods to render Live Data on your map:

mMapControl.setOnWillUpdateLocationsOnMap(locations -> {
   for (MPLocation location : locations) {
       LiveUpdate occupancy = location.getLiveUpdate("occupancy");
       LocationDisplayRule currentDisplayRule = mMapControl.getDisplayRule(location);
       String displayRuleName = location.getId() + "_live";
       if (occupancy != null) {
           OccupancyProperty occupancyProperty = occupancy.getOccupancyProperties();
           LocationDisplayRule occupancyDisplayRule = new LocationDisplayRule
                   .Builder(displayRuleName, currentDisplayRule)
                   .setLabel("people = " + occupancyProperty.getNrOfPeople())
                   .build();
           mMapControl.setDisplayRule(occupancyDisplayRule, location);
       }
   }
});
mMapControl.enableLiveData(LiveDataDomainTypes.OCCUPANCY_DOMAIN, location -> {
   LiveUpdate occupancy = location.getLiveUpdate("occupancy");
   LocationDisplayRule currentDisplayRule = mMapControl.getDisplayRule(location);
   String displayRuleName = location.getId() + "_live";
   if (occupancy != null) {
       OccupancyProperty occupancyProperty = occupancy.getOccupancyProperties();
       LocationDisplayRule occupancyDisplayRule = new LocationDisplayRule
               .Builder(displayRuleName, currentDisplayRule)
               .setLabel("people = " + occupancyProperty.getNrOfPeople())
               .build();
       mMapControl.setDisplayRule(occupancyDisplayRule, location);
   }
});

Note that since there is no guarantee of which Live Data you receive first, and Locations can have multiple Live Data updates on different domains, we recommend checking the lastModifiedTimeStamp of each Live Data update to select which one to render.

While only a few lines of code can get things moving around on a map, there are of course more handles that are relevant to create a robust and user-friendly real-time map experience.

There are two ways to be notified about Live Updates:

  1. On a general level through OnReceivedLiveUpdateListener, which is suitable in scenarios where all Live Updates might potentially affect the end user's decisions, for example when searching broadly for an available meeting room.

  2. On a map-specific level through MapControl, which is suitable in scenarios where the map is the context for the user's actions, for example when browsing the map for an available meeting room nearby

To get Live Updates on a general level the OnReceivedLiveUpdateListener must be set on the LiveDataManager:

liveDataManager.setOnReceivedLiveUpdateListener((topic, message) -> {
           if (message.getDomainType().equals(LiveDataDomainTypes.OCCUPANCY_DOMAIN)) {
               int people = message.getOccupancyProperties().getNrOfPeople();
               ...
           }
        });

To get Live Updates on a map-specific level, the OnWillUpdateLocationsOnMap must be set on MapControl:

mapControl.setOnWillUpdateLocationsOnMap(locations -> {
    for(MPLocation location : locations){
        LiveUpdate liveUpdate = location.getLiveUpdate(LiveDataDomainTypes.OCCUPANCY_DOMAIN);
        ...
    }
}

In order to get notified about state changes and errors related to Live Data, a number of listeners can be set on the LiveDataManager using the following methods and interfaces:

  • setOnReceivedLiveUpdateListener(OnReceivedLiveUpdateListener listener);

  • setOnTopicSubscribedListener(OnTopicSubscribedListener listener);

  • setOnTopicSubscribeErrorListener(OnTopicSubscribeErrorListener listener);

  • setOnTopicUnsubscribedListener(OnTopicUnsubscribedListener listener);

  • setOnTopicUnsubscribeErrorListener(OnTopicUnsubscribeErrorListener listener);

  • setOnLiveDataManagerStateChangedListener(OnLiveDataManagerStateChangedListener listener);

  • setOnErrorListener(OnErrorListener listener);

Live Updates are dependent on network connectivity, so the Live Data Manager will try to recover from common errors like e.g. a network dropout. The Live Data Manager will not try to recover from subscription errors alone, as this could be caused by a non-existing Topic for a given Dataset, thus it does not make sense retrying the failing subscription.

Topic Criterias

Live Updates

Enable Live Data in Your App in Kotlin

Enable Live Data through MapControl in Kotlin

Enable Live Data through LiveDataManager in Kotlin

Rendering Live Data Locations in Kotlin

Handling Live Data Events in Kotlin

Listening for Live Updates in Kotlin

Handling State Changes and Errors in Kotlin

Enable Live Data in Your App in Java

Enable Live Data through MapControl in Java

Enable Live Data through LiveDataManager in Java

Rendering Live Data Locations in Java

Handling Live Data Events in Java

Listening for Live Updates in Java

Handling State Changes and Errors in Java

collaboration with MapsPeople
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​