This tutorial describes how to configure indoor positioning for use with the indoor positioning Android SDK.
The indoor positioning SDK provides an API for developers to create location aware apps for navigation inside buildings at supported venues.
Pre-requisites
The pre-requisites for setting up the indoor positioning Android SDK are as follows:
- Include the indoor positioning SDK dependency in your app's build.gradle.
- Add artifactory to the project's build.gradle.
- Add your HERE license key to your global gradle.properties.
Include the indoor positioning SDK dependency in your app's build.gradle
Change ext.navenioSdkVersion in the top level build.gradle to the latest SDK version available:
dependencies {
api ("com.navenio.android:sdk:$rootProject.ext.navenioSdkVersion") {
exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-accounts'
}
}
Add artifactory to the project's build.gradle
Add the artifactory_repo_key
, artifactory_username
and artifactory_password
(credentials will be supplied by HERE) in your ~/gradle/gradle.properties:
buildscript {
...
dependencies {
classpath "com.android.tools.build:gradle:7.1.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.27.1"
...
}
}
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
apply plugin: 'com.jfrog.artifactory'
}
artifactory {
contextUrl = artifactory_url
resolve {
repoKey = artifactory_repo_key
username = artifactory_username
password = artifactory_password
maven = true
}
}
Note
Gradle requires at least Java version 11, with HERE recommending Java 15 or later.
Add your HERE license keys
The indoor positioning SDK uses the same OAuth2 credentials as the HERE SDK from the same location. Hence, when you have the HERE SDK set up, the indoor positioning SDK OAuth2 keys are set up as well.
Initialize the indoor positioning SDK
Create an instance of the indoor positioning SDK:
lateinit var sdk: NavenioManager
override fun onCreate(...) {
sdk = NavenioManagerProvider.getInstance(this)
}
Fetch indoor positioning data
With a reference to the SDK, fetch the indoor positioning data for a given building:
navenioManager.fetchVenue(<INDOOR_MAP_NAME>, object : FetchVenueListener {
override fun onSuccess(venue: Venue) {
// great success
}
override fun onError(e: Throwable, cached: Venue?) {
// log error
}
})
Indoor positioning data is downloaded and you receive the Venue object. If an error occurs, you will have access to a cached Venue object if you have previously downloaded that venue.
Note
The string is provided by HERE. In subsequent releases, the HERE indoor map ID will be used instead.
Retrieve your location
Create a listener to receive callbacks from the indoor positioning SDK when your position changes:
var locationListener = object : LocationListenerAdapter() {
override fun onLocationChange(location: Location) {
when (location) {
is Location.GeoLocation -> {
Timber.d("onGeoLocation ${location.latitude}, ${location.longitude}")
}
is Location.IndoorLocation -> {
Timber.d("onIndoorLocation ${location.latitude}, ${location.longitude}, ${location.levelId}")
}
}
}
override fun onLevelChange(levelId: String) {
Timber.d("onLevelChange $levelId")
}
}
Listeners should be registered and unregistered in the onResume()
and onPause()
Android lifecycle callbacks:
override fun onResume() {
locationManager.addLocationListener(locationListener)
}
override fun onPause() {
locationManager.removeLocationListener(locationListener)
}
You can start or stop locating anywhere (with data capture turned on by default) using locationManager.startLocating(<INDOOR_MAP_NAME>, captureData = true)
and locationManager.stopLocating()
.
Capture lifecycle events
Use SamplingLifecycleListener
to listen for sampling change events:
var lifecycleListener = object : SamplingLifecycleListenerAdapter() {
override fun onError(event: SamplingEvent.DiagnosticEvent) {
Timber.e("An error occurred: ${event.name}, ${event.description}")
}
override fun onSamplingStateChange(event: SamplingChangeEvent, sessionId: String) {
Timber.d("sessionId: $sessionId, event: ${event.name}")
}
}
Ensure that you add and remove the following listeners:
override fun onResume() {
sdk.addLifecycleListener(lifecycleListener)
}
override fun onPause() {
sdk.removeLifecycleListener(lifecycleListener)
}
Stop and clean up resources
Ensure that you call stopLocating()
when you are finished so that the SDK stops sampling in the background. HERE also recommends calling destroy()
so that the SDK can release its resources. Any listeners are unregistered, and resources that are no longer required when you are finished are released.