The barometric pressure sensor measures the pressure from the air column above the sensor - it does not measure height above ground. Fortunately, there is a (mostly) direct correlation. However, the air is compressed and expanded, and the pressure exerted by the column is not constant. The correlation between pressure and height should be adjusted for this local change in air density. This correction is of great interest to aircraft pilots, so the government is confident that each airport makes this information freely available.
Since temperature and barometric pressure vary randomly all the time, therefore, to be most accurate, you need to know the current standard pressure in your area.
You can first select the current barometer value for the nearest airport, then use this value instead of PRESSURE_STANDARD_ATMOSPHERE. You will need to find out the station identifier or specify the lat / long rectangle. See the technical specifications of the METAR station .
BUT ... If your current error is only 2 meters, this is already excellent. You will never get the exact height from a barometric altimeter - that's why radar altimeters were invented.
http://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&stationString=KSFO&hoursBeforeNow=1&mostRecent=true
This returns the most recent METAR for KSFO (San Francisco):
<?xml version="1.0" encoding="UTF-8"?> <response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XML-Schema-instance" version="1.2" xsi:noNamespaceSchemaLocation="http://aviationweather.gov/adds/schema/metar1_2.xsd"> <request_index>34600121</request_index> <data_source name="metars" /> <request type="retrieve" /> <errors /> <warnings /> <time_taken_ms>1</time_taken_ms> <data num_results="1"> <METAR> <raw_text>KSFO 061756Z 30011KT 10SM FEW008 BKN160 19/13 A2992 RMK AO2 SLP132 T01890133 10189 20150 51006</raw_text> <station_id>KSFO</station_id> <observation_time>2015-08-06T17:56:00Z</observation_time> <latitude>37.62</latitude> <longitude>-122.37</longitude> <temp_c>18.9</temp_c> <dewpoint_c>13.3</dewpoint_c> <wind_dir_degrees>300</wind_dir_degrees> <wind_speed_kt>11</wind_speed_kt> <visibility_statute_mi>10.0</visibility_statute_mi> <altim_in_hg>29.920275</altim_in_hg> <sea_level_pressure_mb>1013.2</sea_level_pressure_mb> <quality_control_flags> <auto_station>TRUE</auto_station> </quality_control_flags> <sky_condition sky_cover="FEW" cloud_base_ft_agl="800" /> <sky_condition sky_cover="BKN" cloud_base_ft_agl="16000" /> <flight_category>VFR</flight_category> <three_hr_pressure_tendency_mb>0.6</three_hr_pressure_tendency_mb> <maxT_c>18.9</maxT_c> <minT_c>15.0</minT_c> <metar_type>SPECI</metar_type> <elevation_m>3.0</elevation_m> </METAR> </data> </response>
You want to display the value sea_level_pressure_mb , which is 1013.2.
Here is a snippet that displays the current barometric pressure on a map of your current location.
I started writing the "right" code for XML parsing, but lost interest when I had to go down the nodes. I left this as a training exercise and instead wrote a version of "hack".
package com.nlited.twopages; import android.app.Activity; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.MapFragment; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import org.w3c.dom.Document; import org.xml.sax.InputSource; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; public class Page2 extends MapFragment implements LocationListener { private static Page2 mObj; private Activity mActivity; private View mView; private MapView mMapView; private GoogleMap mMap; private LocationManager mLocMgr; private String mLocProvider; private Location mLoc; private LatLng mLatLng= new LatLng(43,-122); private boolean mSlpFound= false; private float mSLP= 1012; private String mStationID; private long mNextSlpCheck= 0; static public Page2 getInstance() { if(mObj==null) mObj= new Page2(); return(mObj); } public Page2() { Debug("constructor %s", this.toString()); mObj= this; } @Override public void onAttach(Activity activity) { Debug("onAttach()"); mActivity= (Main)activity; super.onAttach(activity); startLocation(); new Thread(new GetSLP(),"GetSLP").start(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) { mActivity= (Main)getActivity(); Debug("onCreateView()"); super.onCreateView(inflater, container, state); mView= inflater.inflate(R.layout.frag_page2, container, false); mMapView= (MapView)mView.findViewById(R.id.map); mMapView.onCreate(state); mMapView.onResume(); mMap= mMapView.getMap(); mapUpdate(); return(mView); } private void mapUpdate() { MarkerOptions opt = new MarkerOptions(); if(mMap!=null) { String status= mSlpFound ? String.format("%.1f %s",mSLP,mStationID) : "????"; mMap.clear(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLatLng, 15)); mMap.addMarker(opt.position(mLatLng).title(status)); } } private void startLocation() { mLocMgr= (LocationManager)mActivity.getSystemService(Activity.LOCATION_SERVICE); if(mLocMgr==null) { Debug("Location services are not available."); } else if(!mLocMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Debug("GPS is not enabled."); } else { mLocProvider= mLocMgr.getBestProvider(new Criteria(),false); if(mLocProvider==null) { Debug("No GPS providers available."); } else { mLoc = mLocMgr.getLastKnownLocation(mLocProvider); mLocMgr.requestLocationUpdates(mLocProvider,30000,1,this); } } } @Override public void onLocationChanged(Location loc) { Debug("Updated location: %f %f",loc.getLatitude(),loc.getLongitude()); mLoc= loc; mLatLng= new LatLng(mLoc.getLatitude(), mLoc.getLongitude()); if(System.currentTimeMillis() >= mNextSlpCheck) new Thread(new GetSLP(),"GetSLP").start(); mapUpdate(); } @Override public void onStatusChanged(String provider, int status, Bundle state) { Debug("Location %s state is now %d.",provider,status); if(status>0) mapUpdate(); } @Override public void onProviderEnabled(String provider) { Debug("Location %s is now enabled.",provider); } @Override public void onProviderDisabled(String provider) { Debug("Location %s is now disabled.",provider); } private class GetSLP implements Runnable { public void run() { int range; boolean found= false;
Markup:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:background="@color/ForestGreen" tools:context=".Page2" > <TextView android:id="@+id/Page2_Title" android:text="This is Page Two" android:textSize="24pt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:gravity="center" /> <com.google.android.gms.maps.MapView android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@+id/Page2_Title" /> </RelativeLayout>