With the incorporation of GPS devices in smartphones,
Location Based Services
(LBS) have become pretty hot the past few years. The iPhone was the
first to give a huge boost to this kind of applications and now Android
continues on the same path. In this tutorial, I will show you how to
build your first LBS application for Android. The first step is
retrieving the user’s current location and then using his coordinates to
provide data for that location.
In general, the user’s pinpointing on the map is feasible in one of the following ways:
- Using the GPS device that comes with the mobile
- Using the ID of the Cell that the user is currently served by
The
first one is much easier and more accurate (since the second provides
only an approximation). Since these days a big number of phones do have
GPS devices onboard, we will use the first way. The Android SDK’s
emulator can emulate changes in the user’s location and provide dummy
data for his coordinates.
Let’s get started by creating a new
Android Project in Eclipse. I gave it the fancy name
“AndroidLbsGeocodingProject” and used the properties as shown in the
following image:
Note
that I used the Android 1.5 platform version and “3” as the SDK’s min
version. The application is not going to use any of the new super-duper
APIs, so I decided to go with one of the first versions for backwards
compatibility. It is generally a good idea to support as many versions
as possible. You can find information regarding the platform versions
and their corresponding market share
here.
To
start with, we will only add a button which will trigger the retrieval
of the current location’s coordinates from a location provider. Thus,
the “main.xml” file for the application’s interface will be as simple as
this:
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
03 | android:orientation = "vertical" |
04 | android:layout_width = "fill_parent" |
05 | android:layout_height = "fill_parent" |
08 | android:id = "@+id/retrieve_location_button" |
09 | android:text = "Retrieve Location" |
10 | android:layout_width = "wrap_content" |
11 | android:layout_height = "wrap_content" |
In order to get started with the location capabilities of the Android API, the first step is to take reference of the
LocationManager class, which provides access to the system location services. This is done via the
getSystemService of our activity (actually it inherits it from the
Context parent class). Then, we request updates of the device’s location using the method
requestLocationUpdates.
In that method, we provide the name of the preferred location provider
(in our case GPS), the minimum time interval for notifications (in
milliseconds), the minimum distance interval for notifications (in
meters) and finally a class implementing the
LocationListener
interface. That interface declares methods for handling changes in the
user’s location as well as changes in the location provider’s status.
All the above can be translated into code as below:
01 | package com.javacodegeeks.android.lbs; |
03 | import android.app.Activity; |
04 | import android.content.Context; |
05 | import android.location.Location; |
06 | import android.location.LocationListener; |
07 | import android.location.LocationManager; |
08 | import android.os.Bundle; |
09 | import android.view.View; |
10 | import android.view.View.OnClickListener; |
11 | import android.widget.Button; |
12 | import android.widget.Toast; |
14 | public class LbsGeocodingActivity extends Activity { |
16 | private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1 ; |
17 | private static final long MINIMUM_TIME_BETWEEN_UPDATES = 1000 ; |
19 | protected LocationManager locationManager; |
21 | protected Button retrieveLocationButton; |
24 | public void onCreate(Bundle savedInstanceState) { |
26 | super .onCreate(savedInstanceState); |
27 | setContentView(R.layout.main); |
29 | retrieveLocationButton = (Button) findViewById(R.id.retrieve_location_button); |
31 | locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); |
33 | locationManager.requestLocationUpdates( |
34 | LocationManager.GPS_PROVIDER, |
35 | MINIMUM_TIME_BETWEEN_UPDATES, |
36 | MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, |
37 | new MyLocationListener() |
40 | retrieveLocationButton.setOnClickListener( new OnClickListener() { |
42 | public void onClick(View v) { |
43 | showCurrentLocation(); |
49 | protected void showCurrentLocation() { |
51 | Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); |
53 | if (location != null ) { |
54 | String message = String.format( |
55 | "Current Location \n Longitude: %1$s \n Latitude: %2$s" , |
56 | location.getLongitude(), location.getLatitude() |
58 | Toast.makeText(LbsGeocodingActivity. this , message, |
59 | Toast.LENGTH_LONG).show(); |
64 | private class MyLocationListener implements LocationListener { |
66 | public void onLocationChanged(Location location) { |
67 | String message = String.format( |
68 | "New Location \n Longitude: %1$s \n Latitude: %2$s" , |
69 | location.getLongitude(), location.getLatitude() |
71 | Toast.makeText(LbsGeocodingActivity. this , message, Toast.LENGTH_LONG).show(); |
74 | public void onStatusChanged(String s, int i, Bundle b) { |
75 | Toast.makeText(LbsGeocodingActivity. this , "Provider status changed" , |
76 | Toast.LENGTH_LONG).show(); |
79 | public void onProviderDisabled(String s) { |
80 | Toast.makeText(LbsGeocodingActivity. this , |
81 | "Provider disabled by the user. GPS turned off" , |
82 | Toast.LENGTH_LONG).show(); |
85 | public void onProviderEnabled(String s) { |
86 | Toast.makeText(LbsGeocodingActivity. this , |
87 | "Provider enabled by the user. GPS turned on" , |
88 | Toast.LENGTH_LONG).show(); |
For the
LocationListener interface, we implemented the MyLocationListener inner class. The methods in that class just use
Toasts to provide info about the GPS status or any location changes. The only interface element is a
Button which gets hooked up with a
OnClickListener and when it is clicked, the showCurrentLocation method is invoked. Then, the
getLastKnownLocation of the LocationManager instance is executed returning the last known
Location. From a Location object we can get information regarding the user’s
altitude,
latitude,
longitude,
speed etc. In order to be able to run the above code, the necessary permissions have to be granted. These are:
Include those in the AndroidManifest.xml file, which will be as follows:
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
04 | package = "com.javacodegeeks.android.lbs" |
05 | android:versionCode = "1" |
06 | android:versionName = "1.0" > |
08 | < application android:icon = "@drawable/icon" android:label = "@string/app_name" > |
09 | < activity android:name = ".LbsGeocodingActivity" |
10 | android:label = "@string/app_name" > |
12 | < action android:name = "android.intent.action.MAIN" /> |
13 | < category android:name = "android.intent.category.LAUNCHER" /> |
19 | < uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" /> |
20 | < uses-permission android:name = "android.permission.ACCESS_MOCK_LOCATION" /> |
21 | < uses-permission android:name = "android.permission.ACCESS_COARSE_LOCATION" /> |
23 | < uses-sdk android:minSdkVersion = "3" /> |
Next, use the
AVD Manager in order to create a new Android device and make sure that GPS support is included in the features:
Next, use “Run–> Run Configurations…” to create a new configuration for the project:
If
you hit Run, the emulator is started, but nothing will really happen
when the button is clicked. That is because when the emulator starts,
there is no last known location to be retrieved (the
Location instance that is returned is null).
We have to feed the emulator with some dummy data. Go to the
DDMS
view of Eclipse and look for the “Emulation Control” tab. There, among
other things, you will find the “Location Controls” section, which can
send mock location data to the emulator. In the “Manual” tab, just hit
the “Send” button, there are already some coordinates set up.
When
the data are sent to the emulator’s GPS device, our listener will be
triggered and the current location will be printed in the screen in the
form of a
Toast notification.
Now,
a last known location exists, so if you hit the “Retrieve Location”
button, a not null location will be fetched and the coordinates will
again be printed in the screen:
That’s
it. Now you are able to emulate changes in the user’s location and
retrieve updates about them. In the next tutorial, I will show you how
to leverage those coordinates in order to provide useful data to the
user. For now, you can find the Eclipse project
here.
Happy coding!!!
source from: Nikos Maravitsas