Tutorial: Android Location Service Example

Tutorial: Android Location Service Example

Authored By: Laurent Tonon 4 years ago

136425 Page Views
Hi folks,

This tutorial will help you to start using location services (in particular: LocationManager class to get user location and Geocoder to translate location into addresses) and Google Maps on Android.

At the end of this tutorial, you will have a working application that get user location over time, show the approximative address to the user and his location on a map.

1) Start A New Project
The first step is to create a new project
- Click on File -> New -> Android Project
- Give the project a name. I name the project "MarakanaMaps"
- Choose the location you want for your project (it can be in workspace or in a place of your choice)
- Select a Build Target. Make sure that you choose one that has the Google APIs. I choose the following:


- Then, finish creating the project by filling out the Properties section like this:

NOTE: Make sure that you let Create Activity checked since we are going to have an activity containing user location information along with its position on a map


- Click on Finish

2) Create The UI For Our Activity
- By default, when we choose to create the activity, the ADT plugin creates the activity class along with its XML layout file.
- To build our layout, let me first show you what the application is going to look like:


- The layout is composed of a general LinearLayout containing a TextView and a MapView
- Change the layout to be like this one:

- res/layout/main.xml
Code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">


<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Waiting for location..."
android:id="@+id/lblLocationInfo"/>
<!-- <1> -->



<com.google.android.maps.MapView
xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="YOUR_API_KEY_GOES_HERE"/>
<!-- <2> -->

</LinearLayout>

- 1: We give an id to the TextView since we will manipulate its text value later in the code
- 2: Same drill here, we give an id to the MapView so it can be accessed later in the code. Finally since we use Google Maps data, we have to register with the Google Maps service and agree to the applicable ToS so our MapView will be able to obtain data from Google Maps.


2.1) Obtain The API Key
- For the purpose of this tutorial we can register with the MD5 fingerprint of the Android SDK debug certificate
- To get the MD5 fingerprint of the Android SDK debug certificate, execute the following command:
Code:

keytool -list -alias androiddebugkey \
-keystore <path_to_debug_keystore>.keystore \ <1>
-storepass android -keypass android

- 1: Depending on the OS you are developing with, the path to the keystore can be located at the following location:
Windows Vista / Windows 7: C:\Users\<user>\.android\debug.keystore
Windows XP: C:\Documents and Settings\<user>\.android\debug.keystore
Mac OS X / Linux: ~/.android/debug.keystore

- Now, go to the following URL: https://code.google.com/android/maps-api-signup.html and copy/paste the MD5 previously obtained to then get the API key to use.
- Copy paste this API key in the MapView of the res/layout/main.xml layout file and then this is it for the layout, we are not going to modify it anymore!

3) Modify The AndroidManifest.xml
- We need to declare in the manifest that we are using the Google Maps library. Add the following as a direct child of the `<application>` element:

- AndroidManifest.xml
Code:

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<application android:icon="@drawable/icon" android:label="@string/app_name">
...
<uses-library android:name="com.google.android.maps" /> <1>
</application>
</manifest>

- 1: This declares that we are using the Google Maps library

- Since the tiles for the MapView are loaded from the internet we need to give our application the INTERNET permission like this in the <manifest> element:

- AndroidManifest.xml
Code:

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<uses-permission android:name="android.permission.INTERNET" /> <1>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <2>
...
</manifest>

- 1: The application now have the right to open network sockets
- 2: This allows the application to use fine location sensors (GPS...)


4) Run The Application For The First Time
- We are done with the manifest file for the moment. Let us run the application so we can see if the TextView and the MapView are correctly displayed
- To do so, right-click on your project -> Run -> Run

NOTE: In order to run your application, you must have an emulator supporting the Google APIs with the right SDK version (SDK Version 4 in our case).


- The application fails to start and we get an exception. To find out what has just happened, you can view the log statements using the adb logcat in a terminal and here we are looking for the following information:
Code:

E/AndroidRuntime( 516): Caused by: java.lang.IllegalArgumentException: MapViews can only be created inside instances of MapActivity.


- Actually, when we created our activity, the ADT plugin just made inherit from the Activity class like this.

LocationActivity.java
Code:

public class LocationActivity extends Activity


- We now make the changes so it extends from MapActivity:

LocationActivity.java
Code:

public class LocationActivity extends MapActivity


- Eclipse is going to complain if you do not override some methods. Here for the MapActivity, there is only one method to override:

LocationActivity.java
Code:

package com.marakana.tutomaps;

import android.os.Bundle;

import com.google.android.maps.MapActivity;

public class LocationActivity extends MapActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}


- Now we can run the application again and see the following result:


5) Getting The User Location
In this section:
- We want to be able to get user location information such as latitude and longitude.
- We do not display yet a marker on the map but we set the center of the map to be the position of the user.

Below is the code of the LocationActivity class to get user location on Android.
Package statement, import statements and overridden methods that we do not modify are not shown here to keep the code simple:

LocationActivity.java
Code:

...
public class LocationActivity extends MapActivity implements LocationListener { //<1>

private static final String TAG = "LocationActivity";

LocationManager locationManager; //<2>
Geocoder geocoder; //<3>
TextView locationText;
MapView map;
MapController mapController; //<4>

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

locationText = (TextView)this.findViewById(R.id.lblLocationInfo);
map = (MapView)this.findViewById(R.id.mapview);
map.setBuiltInZoomControls(true);

mapController = map.getController(); //<4>
mapController.setZoom(16);

locationManager = (LocationManager)this.getSystemService(LOCATION_SERVICE); //<2>

geocoder = new Geocoder(this); //<3>

Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); //<5>
if (location != null) {
Log.d(TAG, location.toString());
this.onLocationChanged(location); //<6>
}
}

@Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, this); //<7>
}

@Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this); //<8>
}

@Override
public void onLocationChanged(Location location) { //<9>
Log.d(TAG, "onLocationChanged with location " + location.toString());
String text = String.format("Lat:\t %f\nLong:\t %f\nAlt:\t %f\nBearing:\t %f", location.getLatitude(),
location.getLongitude(), location.getAltitude(), location.getBearing());
this.locationText.setText(text);

try {
List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 10); //<10>
for (Address address : addresses) {
this.locationText.append("\n" + address.getAddressLine(0));
}

int latitude = (int)(location.getLatitude() * 1000000);
int longitude = (int)(location.getLongitude() * 1000000);

GeoPoint point = new GeoPoint(latitude,longitude);
mapController.animateTo(point); //<11>

} catch (IOException e) {
Log.e("LocateMe", "Could not get Geocoder data", e);
}
}

...
}

- 1: Our class extends the MapActivity class so it can contain MapViews and it also implements the LocationListener interface to contain callbacks that are called when the LocationManager receives new location updates
- 2: The LocationManager provides access to system location services
- 3: The Geocoder class handles geocoding (transforms an address into lat,long coordinate) and reverse geocoding (gets an address from a latitude,longitude coordinate). In our case, we just use it to do reverse geocoding
- 4: The MapController will be useful to set the zoom level on the map. It will also be used to move the map center point to the current user location
- 5: When the activity starts, it executes the onCreate method. Getting the first user location is often time very long to the user so you might want to display a cached location using the getLastKnownLocation method
- 6: If this method returns a location which is not null, we want to process it so we call onLocationChanged method (overridden in our activity)
- 7: In the onResume method, we request location updates by specifying what is the provider for our locations, the minimum time between notifications in milliseconds, the minimum distance in meters for notifications and finally which LocationListener to use to process new updates
- 8: In the onPause method (in other words, when the activity is not visible on the screen), we do not want to drain battery so we do not listen for location updates anymore. When the activity becomes visible again, the onResume method is called so we now listen for location updates again
- 9: The overridden onLocationChanged method is called when the device receives a new location (with a Location parameter). This is where we convert the location into an address
- 10: The getFromLocation method converts a coordinate (latitude,longitude) into a list of approximative addresses around that coordinate
- 11: This moves the center of the map to the obtained location


6) Try Out The Application
If you start your application in the emulator, you will not be able to see location updates since the emulator is not a physical device. However, there is a way to send location updates to your emulator like this:

- Connect to your emulator like this:
Code:

telnet localhost 5554


- You will be able to send location updates like this:
Code:

geo fix <longitude> <latitude>


- For instance if you send the following command:
Code:

geo fix -122.41914 37.77919


You will get the following result:


The final project application can be downloaded here

If you liked this post you'll probably be interested in these:

25

Comments

Posted on Apr 15, 2015 (4 months ago)

Sham Ch | Nothing

sir im working on android google map for finding nearest shop to my current location sir can we add algorithm such ACO (ant colony optimization algorthm ) for finding nearest shop with google api.

Posted on Mar 21, 2015 (5 months ago)

Stephine Linda | Matrix

Wonderful Blog. I appreciate you sharing such wonderful content! http://www.android-code.com/

Posted on Apr 17, 2013 (2 years ago)

Priyank Prajapati | Student

i'm in a hurry..pls can someone help me... google api key is generate ans work on android 2.2 but MAP is not load in devise.. so please send me map tutorial ... if possible then send me we put name then marker go that place ...

Posted on Dec 19, 2012 (3 years ago)

RITESH SINGH | SOURCEBITS

can anybody help me how to continous get the location. when location changed. Please help me out..

Posted on Nov 07, 2012 (3 years ago)

Tzim Ef | Student

Hello guys ... hello ... i want to learn how send my tag with e-mail or something else

Posted on Oct 15, 2012 (3 years ago)

Paul Prince | Student

sir i am getting the following error while i am run my code [2012-10-15 21:44:03 - MarakanaMaps] Installation error: INSTALL_FAILED_MISSING_SHARED_LIBRARY [2012-10-15 21:44:03 - MarakanaMaps] Please check logcat output for more details. [2012-10-15 21:44:03 - MarakanaMaps] Launch canceled!

Posted on Apr 02, 2012 (3 years ago)

Harsh Dev | Student

The code Given by jeeyakumaran does not give any error but nothing haapens after that too,it just says Waiting for application and nothing happens...please help

Posted on Mar 28, 2012 (3 years ago)

Ashish Juyal | Integra Micro Services

I followed the above code only the difference is that i am running it in Android 2.2 i am not able to see the map in the device(mobile).

Posted on Mar 28, 2012 (3 years ago)

Ashish Juyal | Integra Micro Services

Hi I am a beginner in Android i was trying to locate the current position of the device ,i am getting the latitude,longitudes but not able to see the map ,i got the google api keys also please kindly give some suggestions Thanks in advance

Posted on Mar 27, 2012 (3 years ago)

Zhuodan Zhuo | Xidian University China

hi Jeyakumaran Mayooresan,can u help me with how to geotag photo?? please or anyone else in there please

Posted on Mar 22, 2012 (3 years ago)

Joel Armah | Vodafone

can't any one help, seriously need your assistance. thanks

Posted on Mar 20, 2012 (3 years ago)

Joel Armah | Vodafone

will need the latlong coordinates sent at intervals of every 30seconds. thanks

Posted on Mar 19, 2012 (3 years ago)

Joel Armah | Vodafone

can anyone send me a code to trigger latlong of an android device via sms to a database.thanks

Posted on Nov 30, 2011 (4 years ago)

Adrian Sunny | Dell

i'm in a hurry..pls can someone help me... here's wat exactly i need..by sneding a http request i shd get the location without the maps. and this location shd be displayed on a list table..kindly help.. thanks

Posted on Nov 30, 2011 (4 years ago)

Adrian Sunny | Dell

Hi, I'm new to android.i want to get only the location without the maps.i'm strugglin a bit even with the generation of api key. could u pls help me wit this.. thanks

Posted on Nov 16, 2011 (4 years ago)

Yazid Bsoul | Jordan University of Science and Technology

i generate ApiKey (debug.keystor) that u means... Can you type in the link, which means that is part of graduation project thanksss alottt

Posted on Nov 16, 2011 (4 years ago)

Yazid Bsoul | Jordan University of Science and Technology

i generate ApiKey (debug.keystor) Can you type in the link, which means thanksss alottt

Posted on Nov 14, 2011 (4 years ago)

Alos Unos | Istanbul Technical University

I solved this problem. You must take a GoogleApiKey. You can search with Google.

Posted on Nov 14, 2011 (4 years ago)

Yazid Bsoul | Jordan University of Science and Technology

please pleaze any one help me my problem is the same last post map doesn't appear just squares This problem of the month and I could not be resolved so, please any on help me...

Posted on Oct 17, 2011 (4 years ago)

Alos Unos | Istanbul Technical University

[b] Hi Folks, My problem is this, please help me!!! [img]http://b1110.hizliresim.com/q/k/4t6.jpg[/img][/b]

Posted on Oct 17, 2011 (4 years ago)

Pramod Wadkar | blue planet

sir i want code for finding distance between two locations in KM I am taking locations address as lattitude & langitude

Posted on Oct 17, 2011 (4 years ago)

Pramod Wadkar | blue planet

sir, i want code for my app location findout please send me the code

Posted on Aug 10, 2011 (4 years ago)

Gaurav Gupta | Kochar Soft

Hi RAV_T I tried the link [url]http://kindohm.com/post/1255419375/androidgpsgeocoding.html[/url] Nothing happened same problem not able to fetch latitude and longitude. Once got an exception "Unable to parse response from the server " in getAddresses() Now that to is not coming. Regards Gaurav

Posted on Aug 08, 2011 (4 years ago)

Rav T | Self

Hi, If you need to develop application to get Latitude and longitude as-well-as the Address, there is one reference project. My Target was android 2.1 update 1. Manifest file requirements are same as above. Project don´t have map activity implemented, you have to do on your own. Above Example should help you, no biggie I guess. Here´s the link, with complete description: [url]http://kindohm.com/post/1255419375/androidgpsgeocoding.html[/url] - cheers!!

Posted on Aug 06, 2011 (4 years ago)

Gaurav Gupta | Kochar Soft

Hi This is the same code used from the example specified but nothing is being done. Please help [b]Code [/b] [code]package com.kochar.tutomaps; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.widget.TextView; import android.widget.Toast; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; public class LocationActivity extends MapActivity { MapController mapController; MapView mapview; LocationManager locationManager=null; LocationListener locationListener=null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mapview = (MapView)findViewById(R.id.mapview); mapview.setBuiltInZoomControls(true); mapController = mapview.getController(); mapController.setZoom(16); locationManager = (LocationManager)getSystemService(LOCATION_SERVICE); locationListener = new LocationListener() { private TextView locationDetails; @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public void onLocationChanged(Location location) { makeUseOfNewLocation(location); //Toast.makeText(getApplicationContext(), "New Locationdd", Toast.LENGTH_LONG).show(); } private void makeUseOfNewLocation(Location location) { double lon = (double) (location.getLongitude() * 1E6); double lat = (double) (location.getLatitude() * 1E6); int lontitue = (int)lon; int latitute = (int)lat; Toast.makeText(getApplicationContext(), "New Lontitue = "+ lontitue +"\n New Latitute = "+ latitute, Toast.LENGTH_LONG).show(); locationDetails = (TextView)findViewById(R.id.lblLocationInfo); locationDetails.setText("New Lontitue = "+ lontitue +"\n New Latitute = "+ latitute); GeoPoint geopoint = new GeoPoint(latitute, lontitue); mapController.animateTo(geopoint); //mapview.invalidate(); } }; locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0,locationListener); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); locationManager.removeUpdates(locationListener); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, locationListener); //<7> } @Override protected boolean isRouteDisplayed() { return false; } } [/code] [b]Manifest File[/b] [code]<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.kochar.tutomaps" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="4" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="com.google.android.maps" /> <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> </manifest>[/code]