Jump to main content or area navigation.

Contact Us

Developer Central

Developer Central banner

Android Sample

Envirofacts MultiSystem Representational State Transfer (REST) Application Programming Interface (API)

Overview
This sample will provide the steps to create a simple Android application that can consume Envirofacts Multisystem Data. The Envirofacts Multisystem data is comprised of multiple environmental databases for facility information, including toxic chemical releases, water discharge permit compliance, hazardous waste handling processes, Superfund status, and air emission estimates. The API Data Sample code below will query and display facility information from this database. Following these steps in order will allow the application to recreate the sample project. Download the code sample project in order to get the Eclipse Project files that were created by following the steps.

This solution was built using:

  • Eclipse Indigo Service Release 1 (3.7.1)
  • Android Accessory Download Kit (ADK) for Android platform 2.3.3

Assumptions:

For this sample, create a Google Map based on the device's current Global Positioning System (GPS) location. This map will then display companies provided by the Envirofacts MultiSystem Web service, 10 at a time.

Create a New Project

Create a new Android Project in Eclipse.

Select a Wizard

Name the project. For this example it is named SampleEpa2.

Name Your Project

Click "Next" and the select the build target (Google APIs 2.3.3).

Select Build Target

Click "Next" to finalize the Android Project configuration.

Finalize Configuration

Now that the project has been created additional configurations need to be added to include the Google API and the application permissions. This can be done by replacing the contents of AndroidManafest.xml as follows.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="gov.epa.envirofacts"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="10" />


<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<uses-library android:name="com.google.android.maps" />
<activity
android:label="@string/app_name"
android:name=".SampleEpaActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

In order to use the Google Maps API, the MapView has to be included in main.xml under the res\layout folder. The MapView requires that an API key is provided. The one included in the below snippet will not work. As stated in the assumptions section of this document, one can be obtained by following the steps outlined in the following link: http://code.google.com/android/add-ons/google-apis/maps-overview.html. Exit EPA Disclaimer The below Extensible Markup Language (XML) includes the RelativeLayout which allows the MapView to move and resize as needed.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainlayout"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <com.google.android.maps.MapView
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
    <!-- "Replace appKey this one is invalid" -->
android:apiKey="0gxruET-nFtQGBAD_y718iddbkdAdAqq6Yp6uMh"
/>

   
</RelativeLayout>

Now that the project has been set up and the Google API has been included, some files need to be included from this sample project (two image files with which to mark the Google map).

images/image Files

Two files for parsing the XML from the EPA Web service call.

XML parsing Files

The XML parser puts the output of the Web service into a List of DFEObjects which is a Data Transformation Object (DTO or Bean) so that it can be utilized within the projects. To create the DFEObject create a new class with the following inputs.

Creating DFEObject

Click "Finish" and then open the created file. Replace the contents of the created file with the below java code.

package gov.epa.envirofacts;

import com.google.android.maps.GeoPoint;

public class DFEObject {
private double latitude = 0;
private double longitude  = 0;
private String name="";
private String address="";
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public GeoPoint getGeoPoint(){
return new GeoPoint((int)(latitude*1E6), (int)(longitude*1E6));
}

}

The Google MapView works with overlays to place markers on maps. To create an overlay in this project, create a new class that extends Google's ItemizedOverlay class.

create new class

Replace the contents with the below code so that that the markers that are created can be displayed and clicked on to show more details.

package gov.epa.envirofacts;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;

import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

public class EpaItemizedOverlay extends ItemizedOverlay {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private Context mContext;

                public EpaItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));

                }

                public EpaItemizedOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
mContext = context;
}

@Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);

                }

                @Override
public int size() {
return mOverlays.size();

                }
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}

                @Override
protected boolean onTap(int index) {
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();

return true;
}             
}

In order to display a menu that will allow the user to navigate to the next 10 items on the map, add the following code to bottom of the sampleEpa2Acitivity class.

@Override
                protected boolean isRouteDisplayed() {
                                return false;
                }
                @Override
                public boolean dispatchTouchEvent(MotionEvent ev) {
                   int actionType = ev.getAction();
                   //System.out.println("Action Event="+actionType);
                    switch (actionType) {
                                  case MotionEvent.ACTION_UP:
                                        buildOverlay();
                                        break;
                           }
                      return super.dispatchTouchEvent(ev);
                      }

                @Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean supRetVal = super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE, 0, Menu.NONE, "Last 10");
menu.add(Menu.NONE, 1, Menu.NONE, "Next 10");
return supRetVal;
}

                @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
if(currentPage<1){
currentPage=1;
}
currentPage=currentPage-1;
buildOverlay(currentPage);
return true;
case 1:
currentPage=currentPage+1;
buildOverlay(currentPage);
return true;
}
                     return false;
}

All Android applications start with an activity. When the project was set up, the activity class SampleEpa2Activity was created automatically. In order to get the map and markers to display, this class needs to be modified to pull all of the previous code changes together. Within the SampleEpa2Acitivity class declaration include the following Attributes:

private MapController mapController;
private MapView mapView;
private LocationManager locationManager;
private int currentPage =0;

To update the MapView with the current location of the device that this application is running on, a LocationListener needs to be created. This can be an inner class within the SampleEpa2Activity class. Add the following lines of code before the last bracket in the SampleEpa2Activity class.

public class GeoUpdateHandler implements LocationListener {

                                @Override
public void onLocationChanged(Location location) {
int lat = (int) (location.getLatitude() * 1E6);
int lng = (int) (location.getLongitude() * 1E6);
GeoPoint point = new GeoPoint(lat, lng);
mapController.animateTo(point); //          mapController.setCenter(point);
mapController.setCenter(point);
System.out.println("Location Change");
buildOverlay();
}

                                @Override
public void onProviderDisabled(String provider) {
}

                                @Override
public void onProviderEnabled(String provider) {
}

                                @Override
public void onStatusChanged(String provider, int status, Bundle extras) {


}
}

In order to make a service call to the EPA Envirofacts MultiSystem RESTFUL Service, include the following method declaration in the SampleEpa2Activity class. The service call expects the minimum latitude, minimum longitude, maximum latitude, minimum longitude, starting record, and maximum record. More details on what can be passed to the service can be found at Envirofacts Data Service API.

public String executeQuery(double minLat, double minLon, double maxLat, double maxLon, int page, int pageMulti ) throws IOException, URISyntaxException{
URL url = new URL("http://iaspub.epa.gov/enviro/efservice/multisystem/minLatitude/"+minLat
+"/maxLatitude/"+maxLat+"/minLongitude/"+minLon+"/maxLongitude/"+maxLon
+"/rows/"+((page*pageMulti)+1)+":"+((page+1)*pageMulti));
System.out.println(url.toString());
System.out.println(url.toExternalForm());
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine;
String totalString = "";
while ((inputLine = in.readLine()) != null) {
totalString = totalString.concat(inputLine);
}
in.close();               

return totalString;
}

The service call returns a list of companies within the coordinate range provided. These companies have coordinates, names, and descriptions. This data is all returned in an XML-formatted string. Below are the methods that execute the method above, parse the XML string, then add the markers to the Google MapView overlay. This should be added the SampleEpa2Activity class.

private void getMapPoints(EpaItemizedOverlay itemizedoverlay,
GeoPoint minpoints, GeoPoint maxpoints, int page) {
try {
//Flip min point latitude with max point latitude
String results =executeQuery((double)maxpoints.getLatitudeE6()/1E6,
(double)minpoints.getLongitudeE6()/1E6,
(double)minpoints.getLatitudeE6()/1E6,
(double)maxpoints.getLongitudeE6()/1E6,page,10);
if(results!=null&& results.length()>0){
List<DFEObject> dfePoints = getListOfPointObjects(results);
for (DFEObject dfeObject : dfePoints) {         
itemizedoverlay.addOverlay(new OverlayItem(dfeObject.getGeoPoint(),
dfeObject.getName(),
dfeObject.getAddress()));
}
}
} catch (IOException e) {                                  
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}                                         
}

private List<DFEObject> getListOfPointObjects(String results) {
XmlParser parser = new XmlParser();
List <DFEObject> dfeList = null;
try {
parser.initializeReader();
dfeList  = parser.parseDFEObjectResponse(results);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


return dfeList;
}

The above methods have been encapsulated into a buildOverlay method so that it can be called by other event triggers. This should be added the SampleEpa2Activity class:

protected void buildOverlay(){
                                buildOverlay(0);                     
                }
 
                protected void buildOverlay(int page){
                                mapView = (MapView) findViewById(R.id.mapview);
                                Projection projection;
                                projection = mapView.getProjection();
                               
                                GeoPoint minpoints = projection.fromPixels(1, 1);
                                GeoPoint maxpoints = projection.fromPixels(mapView.getRight(), mapView.getBottom());

                                List<Overlay> mapOverlays = mapView.getOverlays();
mapOverlays.clear();
Drawable drawable = this.getResources().getDrawable(R.drawable.marker);
EpaItemizedOverlay itemizedoverlay = new EpaItemizedOverlay(drawable,mapView.getContext());

getMapPoints(itemizedoverlay,minpoints,maxpoints,page);
if(itemizedoverlay.size()>0){
mapOverlays.add(itemizedoverlay);
}
mapView.invalidate();
}

Finally, the onCreate method needs to be changed from the default one created when the project was created to the following:

public void onCreate(Bundle bundle) {
                                super.onCreate(bundle);
                                setContentView(R.layout.main); // bind the layout to the activity

                                // create a map view
RelativeLayout linearLayout = (RelativeLayout) findViewById(R.id.mainlayout);
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);

                                mapController = mapView.getController();

locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, new GeoUpdateHandler());

                                mapController.setZoom(14); // Zoom 1 is world view
buildOverlay();
}

Top of Page

Run the Application

Run the application and view a map based on the current location with markers on it that are clickable.

Map Clicked Location Marker

If the menu button is clicked, the last/next 10 companies can be displayed.

Last/Next 10 Companies

Top of Page

Locate More Information on Envirofacts MultiSystem Data

Each dataset has a dataset location path that gives the URL that will be needed to reach the data. The sample code can be adjusted to get that data and display it as well. For more information on the RESTFUL Web services provided by the EPA go to Envirofacts Data Service API.

EF Data Service API

Top of Page

Disclaimer | EPA Persistent Cookies Notice

Jump to main content.