Get Started

Import Pinnacle SDK AAR Files

Copy and paste the <sdk file name> file to the folder “\app\libs” of your project, then add it as the dependency in your app build.gradle file:

_implementation files(‘libs/<sdk file name>.aar’)

Add Other Required Dependencies

/

//Add plugin
apply plugin: ‘kotlin-kapt

//used by Pinnacle SDK for REST API calls
implementation ‘com.squareup.retrofit2:retrofit:2.8.1′
implementation ‘com.squareup.retrofit2:converter-gson:2.8.1′
implementation(“com.squareup.okhttp3:okhttp:4.9.3”)
implementation(“com.squareup.moshi:moshi:1.12.0”)
implementation(“com.squareup.moshi:moshi-kotlin:1.12.0”)
implementation(“com.squareup.moshi:moshi-adapters:1.8.0”)


//used by Pinnacle SDK to determine device activity and location
implementation ‘com.google.android.gms:play-services-awareness:19.0.1′
implementation ‘com.google.android.gms:play-services-location:21.0.1′

//other dependencies
kapt(“androidx.room:room-compiler:2.5.0”)
implementation “androidx.work:work-multiprocess:2.8.1”
implementation(“androidx.work:work-runtime-ktx:2.8.1”)
implementation(“androidx.room:room-runtime:2.5.1”)
implementation ‘com.google.code.gson:gson:2.8.9’
implementation ‘org.locationtech.jts:jts-core:1.19.0’17.1.0’

Add Application Permissions

<!--used to access Pinnacle service-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--used to obtain Wi-Fi environment information-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--used to scan Wi-Fi Access Points-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!--used to access device current Latitude and Longitude-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--used to indicate the background calibration process status for Android 13 and above-->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!--optional, used to improve calibration if enabled-->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
android:name="android.permission.POST_NOTIFICATIONS"/>
<!--optional, used to improve calibration if enabled-->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>

Initialize the SDK

SDK initialization must be done using the SDK KEY and the Pinnacle Service URL information. The SDK KEY can be obtained from NextNav Developer Portal for the developer account.

public void init(
@NonNull Context ctx, 
@NonNull String hostEnvironmentName,
@NonNull String developerKey)

The parameter “hostEnvironmentName” is the NextNav service environment URL, developers should use “api.nextnav.io” during evaluation phase. When the application is ready to be commercialized launched, the commercial services agreement for this application will provide the final “hostEnvironmentName” and “developerKey” (SDK KEY) for commercial purpose. Please email to [email protected] for any additional questions on these two parameters.

The following is an example of how to initialize Pinnacle SDK.

private lateinit var sdk: NextNavSdk
private val NEXTNAV_SERVICE_URL = "api.nextnav.io"
private val API_KEY =  <Your API Key>
private lateinit var context: Context
            …...
@RequiresApi(Build.VERSION_CODES.Q)
override fun onCreate(savedInstanceState: Bundle?) {
   	super.onCreate(savedInstanceState)
context = applicationContext
}
private fun initPinnacle() {
sdk = NextNavSdk.getInstance()
sdk.init(context, NEXTNAV_SERVICE_URL, API_KEY)
}

There is another constructor which allows host app initiates the SDK with injected 2D location and related accuracy.

public void init(
@NonNull Context ctx, 
NonNull String hostEnvironmentName,
@NonNull String developerKey,
@NonNull String userProvidedLat,
@NonNull String userProvidedLong,
@NonNull String userProvidedAccuracy)

Start the Calculation of Altitude

To start the altitude calculation, you need to configure the frequency to receive the results from  the Pinnacle Service. There are four different frequencies supported:

Supported FrequencyDescription
ONE_TIMEPinnacle SDK outputs altitude data just once.
ONEPinnacle SDK outputs altitude data once every second until stopAltitudeCalculation is called.
THIRTYPinnacle SDK outputs altitude data once every 30 seconds until stopAltitudeCalculation is called.
SIXTYPinnacle SDK outputs altitude data once every minute until stopAltitudeCalculation is called.

Use the following method to Start altitude calculation:

public void startAltitudeCalculation(
AltitudeCalculationFrequency altitudeFreq
)

NOTE: If the SDK is used in “ONE_TIME” mode to get altitude data, make sure to call sdk.stop() after the calculation is finished. Then initialize SDK instance before processing the next calculation.

The value of altitudeFreq must be one of the 4 values listed in the table above.

Use the following method to Stop the altitude calculation:

public void stopAltitudeCalculation()

Pinnacle SDK also supports 2D Location Injection which allows developers to use the SDK to calculate altitude with a host-app provided (injected) Latitude, Longitude and 2D- Accuracy. This mode can be used if the automated 2D location fetch for altitude calculation by the SDK is not desired. The 2D location injection can be done as follows:

public void startAltitudeCalculation(
AltitudeCalculationFrequency altitudeFreq, 
String userProvidedLat, 
String userProvidedLong, 
String userProvidedAccuracy
)

The parameter “userProvidedAccuracy” is accuracy (or sometimes referred to as Uncertainty) of the 2D position/location provided to the SDK for Altitude calculation. This unit is in meters. A value of 0 indicates that the 2D location is very accurate. Typically, the accuracy value can range from a few meters to a few hundred meters. Any location accuracy larger than 1000m is not very useful and host App should refrain from injecting such large values for altitude determination.

NOTE: Once a 2D location is injected via the startAltitudeCalculatuon function, the SDK will no longer automatically fetch 2D location from the device for altitude calculation. The host-app/developer must ensure that the injected location value is updated as needed by calling the stopAltitudeCalculation function for the SDK to use the latest/correct location data otherwise the location data may become stale relative to where the altitude is being computed by the SDK. While injecting 2D Location for “ONE_TIME” mode to get altitude data, it does not need to call sdk.stop()  after the calculation is finished or reinitialize the SDK instance before processing the next calculation.

Receive Data from SDK

SdkStatusNotification and AltitudeContextNotification are the two components to receive the data from SDK and Pinnacle service. These two components need to be initialized and added as Observer before calling SDK init() method.

SdkStatusNotification is an observable object to notify the implemented observer about the status of Pinnacle SDK.

final public class SdkStatusNotification extends Observable {
      public Integer code; //SDK message
      public long timestamp; // epoch timestamp of message
}

The following is an example of how to get the status message of SDK:

private lateinit var sdkMessageObservable: SdkStatusNotification
…
sdkMessageObservable = SdkStatusNotification.getInstance()
sdkMessageObservable.addObserver(this)
...
if (o is SdkStatusNotification) { 
when (o.code) {
SdkStatus.STATUS_MESSAGES.INIT_SUCCESS.code -> {
		// SDK is initialized successfully, it’s ready to start altitude calculation
       	}
}
}

SdkStatusNotification supports the following error codes:

Error CodeDescriptionNotes
800SDK initialization success 
801SDK initializing in progress 
802Initializing pressure providerThe test mobile phone may not include a barometric sensor, please check the list of NextNav verified mobile phones in section 6
803Initializing location provider 
804No location availableConsider as initialization failed after 10 seconds
805No pressure availableConsider as initialization failed after 10 seconds
806SDK initialization failed 
808SDK is already initialized 
810SDK is not initialized 
811SDK stop successfully 
815Input host URL is invalid 
830Altitude mode is activated 
832Waiting for pressure for assistance fetch 
833Waiting for location for assistance fetch 
835Altitude mode is deactivated 
870Manual barometer calibration success 
871Manual barometer calibration in progress 
872Manual barometer calibration failedThe end-user may be directed to manually calibrate in a different place/location and at a different time
876Device pressure reading is changing too fast and/or user does not seem to be stillThe Pinnacle SDK cannot run the manual-calibration operation due to rapid movement/change. The end user may be directed that a calibration is needed when the user’s device is not moving.
877Not a good place (Ex: outside coverage area etc.) to collect dataThe end-user may be directed to manually calibrate in a different place/location and at a different time
896Activity permission is needed 
898Location permission is needed 
899Storage permission is needed 

After the SDK is successfully initialized, the calculated altitude data, and the related error messages can be retrieved by the developer via the simple expedient of declaring the object of AltitudeContextNotification.

final public class AltitudeContextNotification extends Observable {
    public Double height = null; //Height above Ellipsoid (HAE) in Meters WGS-84 Datum 
    public Double heightUncertainty = null; //Height Uncertainty in Meters at 90% confidence. This is deprecated, heightUncertainty90 can be used instead.
  public Double heightUncertainty68 = null; // Height Uncertainty in Meters at 68% confidence
  public Double heightUncertainty90 = null; // Height Uncertainty in Meters at 90% confidence
  public Double heightUncertainty95 = null; // Height Uncertainty in Meters at 95% confidence
    public Double heightHat = null; //Height above Terrain (HAT) in Meters
    public Double heightHatUncertainty = null; // Height above Terrain Uncertainty in Meters at 90% confidence. This is deprecated, heightHatUncertainty90 can be used instead.
    public Double heightHatUncertainty68 = null; // Height above Terrain Uncertainty in Meters at 68% confidence
   public Double heightHatUncertainty90 = null; // Height above Terrain Uncertainty in Meters at 90% confidence
  public Double heightHatUncertainty95 = null; // Height above Terrain Uncertainty in Meters at 95% confidence
    public String floorNumber; //Floor Number if in Known Building
    public Double floorConfidence = null; //Floor Confidence
    public String address; //Address of Current Location
    public String addressConfidence; //Address Confidence
    public Integer statusCode; //Altitude Service Status Code
    public Integer errorCode; //Additional error code if applicable
    public Boolean manualBaroCalRequired; //User assisted calibration required
    public long timestamp; //epoch timestamp of altitude data
}

Note: floorNumber, floorConfidence, address and addressConfidence are not supported currently.

The SDK utilizes the AltitudeContextNotification object to report the HAE and HAT uncertainty (sometimes referred to as “accuracy”) values at 95%, 90% and 68% confidence levels. The uncertainty value indicates that the altitude value generated by the SDK could lie in a range of (altitude-value – altitude uncertainty) and (altitude-value + altitude uncertainty) at a given confidence level.

For example, if the SDK generates a HAT value of 2m and HAT-Uncertainty value of 3m at 90% confidence. Then there is 90% confidence that the reported HAT value lies between –1m and 5m.

The uncertainty value is not intended to be an estimate of error relative to the actual vertical location of the mobile device, but instead is provided primarily to convey a quality metric for the altitude estimate. The larger the uncertainty the poorer the quality of the altitude estimate. The SDK reports this quality metric at 95%, 90% and 68% confidence levels.

These different levels are reported to enable the developer to choose the uncertainty confidence level best suited for the application.  Most applications should use the 68% confidence level to be consistent with the 68% confidence level reported for 2D location uncertainty (68% is the 2D location uncertainty confidence level is typically reported in most commercial devices).

If the manualBaroCalRequired indicator is returned by the SDK as true, then it is an indicator that the barometer sensor on the device needs to be calibrated. There are 2 options for the host-app to achieve this:

1.         Allow the SDK to run in an initialized state for an additional period of time (even if altitude data is not needed by the Host-App) to allow it to perform background calibration.

2.         Use the manual-calibration (or user-assisted calibration) function as discussed section 5.1 below.

The Host-App must run the SDK in altitude calculation mode from time-to-time (once every 3 – 4 days) to check the calibration state of the device’ baro-sensor. The “ONE-time mode is sufficient for this calibration check.

The statusCode field in the AltitudeContextNotification object is used to provide the host-app an update on state of assistance data fetch operation performed by the SDK when it is in altitude calculation mode.

Error CodeDescriptionNotes
200Successful assistance data delivery, including HAE, HAT and uncertainty data 
400General server failure 
403Invalid API Key 
6002D location is out of NextNav Pinnacle service area 
610Inside Pinnacle coverage/service area but reference pressure data is NOT available 
620Inside Pinnacle coverage/service area but barometer calibration data is NOT availableCheck manual calibration Indicator and request user to perform user assisted (manual) calibration steps
630Combination of 610 and 620 CodesCheck manual calibration Indicator and request user to perform user assisted (manual) calibration steps
640Barometer calibration data is staleCheck manual calibration Indicator and request user to perform user assisted (manual) calibration steps

The errorCode field in the AltitudeContextNotification object is used to provide the host-app an update on the state of altitude computation in the SDK at the time for altitude generation.

Error CodeDescriptionNotes
850Connecting to Pinnacle service 
851Server request failed due to network issue 
852Phone Pressure Data is Stale 
853Phone Location Data is Stale 
854Reference Data is Stale 

The following is an example of how to retrieve the calculation results of altitude data from SDK:

private lateinit var altitudeObservable: AltitudeContextNotification
…
altitudeObservable = AltitudeContextNotification.getInstance()
altitudeObservable.addObserver(this)
…
if (o is AltitudeContextNotification) {
    	if (Date().time - o.timestamp <= 1000) {
   	    when (o.statusCode) {
            	     200 -> {
       		if (o.heightHat != null && o.heightHatUncertainty != null 
&& o.height != null && o.heightUncertainty != null) {
         	val hat = o.heightHat.toDouble()
         	val hatUnc = o.heightHatUncertainty.toDouble()
         	val hae = o.height.toDouble()
         	val haeUnc = o.heightUncertainty.toDouble()
 }
}
}
}

Improve the quality and quantity of collected data

The SDK provides additional status codes to the app as shown below. Apps, based on their specific use-case could use this information for aspects like user messaging, introducing additional meta-data to qualify the vertical location, etc.

The warningCode field in the AltitudeContextNotification is used to return the warning code when related filter is enabled.

Warning CodeDescriptionNotes
836High delta in pressure 
837High delta in location 

The following is an example of how to set up filters for altitude calculation.

if (o is AltitudeContextNotification) { 
    	if (Date().time - o.timestamp <= 1000) { 
   	    when (o.warningCode) { 
		   WarningMessages.HIGH_DELTA_LOCATION.code -> { 
   			    //handling this warning code   			    
  		   } 
		   WarningMessages.HIGH_DELTA_PRESSURE.code -> { 
   			    //handling this warning code
  		   }
} 
}

}

Initiate a Barometer Calibration (baro-calibration)

The Pinnacle SDK provides a method called “startBarocalUpload” for the app to direct the SDK to perform data collection for barometer calibration purposes when the app determines the most appropriate time and location. More information on the most suitable time and location to perform barometer sensor calibration is described in the “App Note — NextNav Pinnacle Service Best Practices” document on the NextNav Developer Portal. When “startBarocalUpload” method is called, the SDK collects pressure and location data directly from the device to facilitate the barometer calibration process.

The following method is used to initiate baro-calibration process:

public void startBarocalUpload(BarocalCallback callback, boolean isRestartBarocal)

Note: using true for parameter isRestartBarocal to initiate baro-calibration process The SDK also supports a mode where the app can provide the 2D location to the SDK for the baro-calibration process by calling the “setAltitude” function. When this function is called along before the “tartBarocalUpload” function, the SDK uses the 2D location provided by the App and does NOT read it directly from the device. The SDK reads the pressure data directly from the device.

The host App needs to use the following method to set up the location before calling the above method:

public void setAltitude(String userProvidedLat, String userProvidedLong, String userProvidedAccuracy, String userProvidedPressurePascal)

Note: using null for parameter userProvidedPressurePascal to set up 2D location only

Note: from version 2.x, using empty string “” for parameter userProvidedPressurePascal to set up 2D location only