Developing Apps Using Atmospheric Pressure Sensor Feb 1, 2013

About This Article

This article was written to inform Android developers about different ways of using atmospheric pressure information and to describe how to retrieve atmospheric pressure information. This article was written under the assumption that the reader possesses a basic understanding of the Android platform and Java programming.

For more information about the Android platform, please visit the link below.
http://developer.android.com/

For technical documents provided by Samsung, please visit the link below.
http://developer.samsung.com/home.do

Introduction

By default, Android provides APIs for acquiring data from various device sensors. You can use these APIs to display sensor data or analyze sensor data to create interactive programs. The following looks at how to acquire and use atmospheric pressure information from the device’s atmospheric pressure sensor.

For more information about using sensors in Android, visit the link below.
http://developer.android.com/guide/topics/sensors/sensors_overview.html

To acquire atmospheric pressure information in Android, the device must be equipped with a atmospheric pressure sensor. As of January, 2013, Samsung devices equipped with atmospheric pressure sensors include the Galaxy Note, Galaxy S3, Galaxy Note 2, and Galaxy Nexus S series.

Application of Atmospheric Pressure Information

By using the value changes in the atmospheric pressure information, you can approximately forecast the weather, for example, “The weather will be cloudy.” When used in combination with sea level atmospheric pressure information, you can calculate the elevation of your current position.

Moreover, using atmospheric pressure information to calculate elevation has a few advantages over other elevation calculation methods (such as using the Google Elevation API or GPS).

Firstly, you can calculate a relatively more accurate elevation compared to other calculation methods, and the elevation can be measured even indoors. When using the Google Elevation API, you cannot calculate the elevation inside a building. GPS is also not a viable option for use inside a building. And in many cases, the elevation measured using GPS is inaccurate. However, when the elevation is calculated using the atmospheric pressure sensor, you can calculate the elevation with relatively higher accuracy by using the atmospheric pressure information and sea level atmospheric pressure information.
Secondly, you can immediately show small changes in the elevation. For example, if you take an elevator, you can use the atmospheric pressure information to show the changes in elevation as the elevator travels. The same applies to elevation changes on the surface of the earth. It also uses less network traffic than the Google Elevation API does, which has to retrieve the elevation again through the API when the position changes.

You can utilize these advantages to develop an altimeter that offers accurate altitude, calculate calorie consumption during exercises, such as running or jogging, and identify different floors within a building.

The current elevation from the sea level can be calculated easily based on atmospheric pressure information of the current position and sea level pressure information by using the API provided in Android.

Below is a description of the API from the Android developers website.

Public Methods
Public Methods
static float getAltitude (float p0, float p)
Computes the Altitude in meters from the atmospheric pressure and the pressure at sea level.

http://developer.android.com/reference/android/hardware/SensorManager.html#getAltitude(float, float)

This API can also be used to calculate the elevation difference between two positions based on atmospheric pressure difference. Since the atmospheric pressure changes depend on the position, the two positions must be at the same or similar position on the horizontal plane. One example would be calculating the elevation difference between different floors within the same building. You can calculate the difference through the following equation.

float altitude_difference = getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2) - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
[Code 1] Calculate the elevation difference between two positions

You can also acquire vertical speed by calculating the changes in pressure value over a certain amount of time in two identical or similar positions on the horizontal plane. Atmospheric pressure changes over time and depends on the weather. Therefore, speed must be calculated only over a short amount of time.

The speed can be calculated by using the following equation.

float vertical_speed = ( getAltitude(sea level pressure, pressure at t0) – getAltitude(sea level pressure, pressure at t1) / ( t1 – t0 );
[Code 2] Acquire vertical speed

To calculate the elevation, you need the sea level atmospheric pressure of the current position. As described in the Android platform API description, if the sea level atmospheric pressure value cannot be acquired then SensorManager.PRESSURE_STANDARD_ATMOSPHERE, which is the standard sea level atmospheric pressure value, can be used. However, the elevation data calculated with this value may have lower accuracy as the standard value will differ from the actual sea level atmospheric pressure value.

Some weather forecast providers also provide APIs that you can use to retrieve weather information at a specific position. This data sometimes contains sea level atmospheric pressure information. You can use this information to calculate the sea level elevation as accurately as possible. However, there may be small differences due to the distance from the current position to where the sea level atmospheric pressure is actually measured or due to information update intervals.

The next section looks at how to retrieve atmospheric pressure sensor data from the device and sea level atmospheric pressure.

Retrieving Atmospheric Pressure Information from the Device

The steps for retrieving atmospheric pressure data from the device are identical to retrieving other sensor data. First, you must create a SensorManager class. This class is used to register listeners to receive the data from the sensor. Just as with LocationService, the listener is registered in the onResume() method and unregistered in onPause() method in most cases.
The following code illustrates an example.

public class PressureSensor extends Activity {

  private SensorManager mSensorManager = null;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pressure_sensor);
    
    // get SensorManager instance.
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  }

  @Override
  protected void onResume() {
    super.onResume();
    // Register listener
    mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE), SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
    super.onPause();
    // Unregister listener
    mSensorManager.unregisterListener(mSensorListener);
  }
  
  private SensorEventListener mSensorListener = new SensorEventListener() {
    
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
      // when accuracy changed, this method will be called.
    }
    
    @Override
    public void onSensorChanged(SensorEvent event) {
      // when pressure value is changed, this method will be called.
      float pressure_value = 0.0f;
      float height = 0.0f;
      
      // if you use this listener as listener of only one sensor (ex, Pressure), then you don't need to check sensor type.
      if( Sensor.TYPE_PRESSURE == event.sensor.getType() ) {
        pressure_value = event.values[0];
        height = SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_value);
      }
    }
  };
}
[Code 3] Retrieving Atmospheric Pressure Information from the Device

The code to handle atmospheric pressure information must be entered in the onSensorChanged() method.

Please note that the unit of atmospheric pressure data retrieved from the sensors is mBar (= hPa).

Retrieving Sea Level Atmospheric Pressure Information

In many cases, weather forecast providers also include atmospheric pressure information in the current weather information. The companies listed below let you use their APIs after acquiring an API key through user registration. Each company has a different maximum number of requests limit per day. You must switch to a paid plan or contact the company to sign up for an additional plan to have more requests processed.

The example code below explains how to retrieve sea level atmospheric pressure information of a given longitude and latitude using WeatherBug’s API.

public class PressureSensor extends Activity {

  ...

  private float sea_level_pressure = SensorManager.PRESSURE_STANDARD_ATMOSPHERE;
  
  public static final String TAG_PRESSURE = "aws:pressure";
  public static final String TAG_LONGITUDE = "aws:longitude";
  public static final String TAG_LATITUDE = "aws:latitude";


  private void updatePressure(){
    Thread task = new Thread(new Runnable(){
      public void run() {
        sea_level_pressure = GetRefPressure(longitude,latitude);
        Log.d(TAG,"updated! " + sea_level_pressure);
      }});
    task.start();
  }  // this function is 
  public float GetRefPressure(double longitude, double latitude) {
    InputStream is = null;
    float pressure = 0.0f;
    try {
      String strUrl = String.format("http://(insert your API Key).api.wxbug.net/getLiveWeatherRSS.aspx?ACode=(insert your API)&lat=%f&long=%f&UnitType=1&OutputType=1",latitude,longitude );
      URL text = new URL(strUrl);
      Log.d(TAG,text.toString());

      URLConnection connection = text.openConnection();
      connection.setReadTimeout(30000);
      connection.setConnectTimeout(30000);

      is = connection.getInputStream();
      
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder domParser = dbf.newDocumentBuilder();
      Document xmldoc = domParser.parse(is);
      Element root = xmldoc.getDocumentElement();
      
      pressure = Float.parseFloat(getTagValue(TAG_PRESSURE, root));
      float lon = Float.parseFloat(getTagValue(TAG_LONGITUDE, root));
      float lat = Float.parseFloat(getTagValue(TAG_LATITUDE, root));
    } catch (Exception e) {
      Log.e(TAG, "Error in network call", e);
      pressure = SensorManager.PRESSURE_STANDARD_ATMOSPHERE;
    } finally {
      try {
        if(is!=null)
          is.close(); 
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return pressure;
  }
  public String getTagValue(String sTag, Element eElement) {
    NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
    Node nValue = (Node) nlList.item(0);
    return nValue.getNodeValue();
  }
}
[Code 4] Retrieving Sea Level Atmospheric Pressure Information

In the example code above, the GetRefPressure() method, which handles networking tasks, runs on another thread.

Since the HTTP query is used to retrieve the results, permission for accessing the internet must be added to AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.sec.pressuresensor"
  android:versionCode="1"
  android:versionName="1.0" >

  <uses-permission android:name="android.permission.INTERNET"/>
  ...  

</manifest>
[Code 5] Add permission to AndroidManifest.xml

In the GetRefPressure() method, the accurate API key received from WeatherBug must be entered in the URL to successfully retrieve the sea level atmospheric pressure information of the given longitude and latitude.

In the example, DocumentBuilderFactory was used to analyze the result XML, and sea level atmospheric pressure information was retrieved by finding the matching string (TAG_PRESSURE).

In addition to the DOM parser used above, the SAX parser or XmlPullParser can be used to analyze the XML. For more information on using the other parsers, please visit the links below.