The Android SDK offers a nice API to receive information about available providers for location based services and get the current location and coordinates.

In this short tutorial we’re going to build a small activity that displays a list of available location providers and shows the current position using GPS services.

Example Application

  • Create a new Android Project using ADT and your IDE with a package named com.hascode.android.location_app

  • Add the permissions needed to the AndroidManifest.xml – it should look like this

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    	package="com.hascode.android.location_app" android:versionCode="1"
    	android:versionName="1.0">
    	<application android:icon="@drawable/icon" android:label="@string/app_name">
    		<activity android:name=".LocationActivity" android:label="@string/app_name">
    			<intent-filter>
    				<action android:name="android.intent.action.MAIN" />
    				<category android:name="android.intent.category.LAUNCHER" />
    			</intent-filter>
    		</activity>
    
    	</application>
    	<uses-sdk android:minSdkVersion="7" />
    
    	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    	<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
    	<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"></uses-permission>
    </manifest>
  • Create a layout with one text view and two buttons in the main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <TableLayout android:layout_width="fill_parent"
    	android:layout_height="fill_parent" android:orientation="vertical"
    	xmlns:android="http://schemas.android.com/apk/res/android">
    	<TextView android:id="@+id/output" android:layout_width="wrap_content"
    		android:layout_height="wrap_content" android:text="@string/loading">
    	</TextView>
    	<Button android:id="@+id/btShowProviders" android:layout_width="wrap_content"
    		android:layout_height="wrap_content" android:text="@string/showProviders">
    	</Button>
    	<Button android:id="@+id/btShowLocation" android:layout_width="wrap_content"
    		android:layout_height="wrap_content" android:text="@string/showLocation">
    	</Button>
    </TableLayout>
  • Externalize the strings in the strings.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
     <string name="app_name">LocationApp</string>
     <string name="loading">loading...</string>
     <string name="showProviders">Show available providers</string>
     <string name="showLocation">Listen to coordinate updates</string>
    </resources>
  • Create the activity LocationActivity

    package com.hascode.android.location_app;
    
    import java.util.List;
    
    import android.app.Activity;
    import android.content.Context;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.location.LocationProvider;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class LocationActivity extends Activity implements LocationListener {
    	// attrs
    	private static final String TAG = "com.hascode.android.location-app";
    	private LocationManager locationManager;
    	private static final String PROVIDER = "gps"; // for this tutorial we simply
    	// assume that this provider
    	// exists
    
    	// ui elements
    	private TextView output;
    	private Button btShowProviders;
    	private Button btShowLocation;
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.main);
    
    		output = (TextView) findViewById(R.id.output);
    		btShowProviders = (Button) findViewById(R.id.btShowProviders);
    		btShowLocation = (Button) findViewById(R.id.btShowLocation);
    
    		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    		if (locationManager == null) {
    			Log.w(TAG, "no location manager found");
    			output.setText("no location manager no fun ..");
    		} else {
    			btShowProviders.setOnClickListener(new View.OnClickListener() {
    				@Override
    				public void onClick(View view) {
    					showProviders();
    				}
    			});
    
    			btShowLocation.setOnClickListener(new View.OnClickListener() {
    				@Override
    				public void onClick(View view) {
    					showLocation();
    				}
    			});
    		}
    	}
    
    	/**
    	 * shows the list of available location providers
    	 */
    	private void showProviders() {
    		List<String> providers = locationManager.getAllProviders();
    		Log.d(TAG, "available providers found: " + providers.size());
    		StringBuilder s = new StringBuilder();
    		for (String provider : providers) {
    			s.append(provider);
    			s.append("\n");
    		}
    		output.setText(s.toString());
    	}
    
    	/**
    	 * displays the current location using the gps provider
    	 */
    	private void showLocation() {
    		LocationProvider gps = locationManager.getProvider(PROVIDER);
    		if (gps == null) {
    			Log.w(TAG, "gps provider not found");
    			return;
    		}
    
    		locationManager.requestLocationUpdates(PROVIDER, 1200, 5, this);
    		Log.d(TAG, "listening to gps events started");
    	}
    
    	/*
    	 * (non-Javadoc)
    	 *
    	 * @see
    	 * android.location.LocationListener#onLocationChanged(android.location.
    	 * Location)
    	 */
    	@Override
    	public void onLocationChanged(Location location) {
    		String result = String.format(
    				"Your coords: latitude %f is longitude is %f", location
    						.getLatitude(), location.getLongitude());
    		Log.d(TAG, "location update received: " + result);
    		output.setText(result);
    	}
    
    	/*
    	 * (non-Javadoc)
    	 *
    	 * @see
    	 * android.location.LocationListener#onProviderDisabled(java.lang.String)
    	 */
    	@Override
    	public void onProviderDisabled(String provider) {
    		Log.d(TAG, "the following provider was disabled: " + provider);
    	}
    
    	/*
    	 * (non-Javadoc)
    	 *
    	 * @see
    	 * android.location.LocationListener#onProviderEnabled(java.lang.String)
    	 */
    	@Override
    	public void onProviderEnabled(String provider) {
    		Log.d(TAG, "the following provider was enabled: " + provider);
    	}
    
    	/*
    	 * (non-Javadoc)
    	 *
    	 * @see android.location.LocationListener#onStatusChanged(java.lang.String,
    	 * int, android.os.Bundle)
    	 */
    	@Override
    	public void onStatusChanged(String provider, int status, Bundle extras) {
    		Log.d(TAG, String.format(
    				"Provider status has changed. provider: %s, status: %d",
    				provider, status));
    	}
    }
  • Run the app on your emulator and use ddms or the emulator control view if you’re using eclipse like me

Screenshots

show providers 202x300 show coordinates 200x300 eclipse coordinates emulation 192x300

Converting to a Maven Project

If you want to use Maven with your project, take a look at this article – my pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.hascode.android.location_app</groupId>
 <artifactId>location-app</artifactId>
 <packaging>apk</packaging>
 <name>hasCode.com - Sample Location App</name>
 <version>0.1</version>
    <dependencies>
        <dependency>
            <groupId>android</groupId>
            <artifactId>android</artifactId>
            <version>2.1_r1</version>
           <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.jayway.maven.plugins.android.generation2</groupId>
                <artifactId>maven-android-plugin</artifactId>
                <configuration>
                    <sdk>
                        <path>${env.ANDROID_HOME}</path>
                        <platform>1.6</platform>
                    </sdk>
                    <deleteConflictingFiles>true</deleteConflictingFiles>
                </configuration>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
 </project>

Logging and Filtering

Take a look at the logs using the adb tool and filter for entries with the tag “com.hascode.android.location-app“:

adb -s emulator-5554 shell
# logcat com.hascode.android.location-app:D *:S
D/com.hascode.android.location-app(  209): available providers found: 1
D/com.hascode.android.location-app(  209): listening to gps events started
D/com.hascode.android.location-app(  209): listening to gps events started
D/com.hascode.android.location-app(  209): available providers found: 1
D/com.hascode.android.location-app(  209): listening to gps events started

Article Updates

  • 2015-03-03: Table of contents added.