Search code examples
androidkotlingpsgisandroid-gnss

Getting mean sea level altitude on Android instead of ellipsoidal elevation


For geospatial purposes I need my Android application to deliver the users current mean sea level elevation.

My first attempt was to use the system's own locationManager. When requesting a location it delivers exactly those properties I have to evaluate - longitude, latitude and altitude. Perfect!


val locationManager = getSystemService(context, LocationManager::class.java) ?: return@launch
val locationListener = LocationListener { location ->
    Text("Lat: ${location.latitude}°")
    Text("Lng: ${location.longitude}°")
    Text("z: ${location.altitude}[m NN]") // This is not [m NN] but metres over WGS84 ellipsoid
    Text("horizontal_accuracy: ${location.accuracy}[m]")
    Text("vertical_accuracy ${location.verticalAccuracyMeters}[m]")
    return@LocationListener
}
val criteria = Criteria()
criteria.powerRequirement = Criteria.POWER_HIGH
criteria.accuracy = Criteria.ACCURACY_FINE
val bestProvider = locationManager.getBestProvider(criteria, true) ?: LocationManager.GPS_PROVIDER
locationManager.requestLocationUpdates(bestProvider, 100L, 0f, locationListener)

But when I had a closer look at my altitude result I noticed that the value was 40 meters higher than I expected. Looking further into the topic I learned that Android's LocationManager delivers ellipsoidal altitudes. So the difference I noticed are geoid undulations. I can't use the data the way it is right now as I need mean sea level altitudes.

I know I could include a EGM model into my application, but those calculations are rather complicated and the model would inflate my applications file size. JavaScript (web browser) applications and iOS applications resolve mean sea level altitudes - Is there any way to achieve this on Android without calculating too much? Is there any parameter I didn't see?

EDIT:

As I said there is the possibility to include an EGM96 model. But this will inflate the app by lots - just for the purpose of getting better elevation data.

https://stackoverflow.com/a/12811478

But this seems like a lot of overhead.


Solution

  • From API level 34+ the Location class will also have the property mslAltitudeMeters. This is what I was looking for. As soon as 34 / Android 14 is getting released it will be possible to simply use requestLocationUpdates() on the LocationManager and easily get Mean Sea Level Altitudes without having to evaluate NMEA strings.