Total votes: 0
Print: Print Article
Please login to rate or to leave a comment.
Published: 18 Jun 2012
In Windows Phone and iOS getting the current position of the device in terms of latitude and longitude and then placing a marker on a map is a relatively easy task. In Android, things tend to be a bit more complicated and require a bit more attention and preliminary work. My purpose with this article is just touching on the various steps required to capture information about the current location and displaying that on a map view.
You’ll see how to use the location service and various location providers and how to configure your application to use the Google Maps library via an ad hoc MapView widget. As first step, let’s start with a simple basic Android application that shows the latitude and longitude of the current location.
Getting Ready for Getting the Current Location
The sample application has a button that when clicked shows latitude and longitude via a toast message. Here’s some sample XML layout for the main screen.
For this first example, the activity doesn’t have to be anything special and it just does the usual chores such as getting references for the widgets in the XML layout and attaching a few event listeners where required. Here’s the code:
This code just provides the minimal scaffolding for any Android application with a clickable button. The grabLocationInfo method is where you are expected to place the code that reads the position and does something with the information.
In Android the current position is returned by the Location Manager system component. In order to place successful calls to this component, however, you need to get appropriate permissions. Here’s how the application manifest file looks like once fully configured for location services.
You need to get two permissions: to access the Internet and the ACCESS_FINE_LOCATION permission. To be precise, you have two feasible permissions to choose from: ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION. The difference is well explained by the name: fine versus coarse. It’s all about the precision that you can get about the current user location. You can choose either permission, but choosing one is required otherwise the application will fail as soon as the location services are invoked.
The Location Provider
The Android Location Manager relies on a provider component to acquire the actual information about the user location. There are two built-in providers: one utilizes the device’s GPS; the other utilizes the source of the wifi signal to figure out the geographical position. Of the two, the GPS provider is most accurate, but also it is harder to set to work: it may not work indoor, it is slower and more battery hungry. You select the provider of choice when you set up the location manager. Here’s the code to add to the definition of the grabLocationInfo method:
First and foremost, the code gets a reference to the location manager; next it asks the manager to return location updates. You do this by passing a callback function that will invoked whenever the location changes. The callback takes the form of the LocationListener class that you have seen in the previous code snippet.
The listener is the place where you insert the code that actually does something significant when the location changes. This may be anything useful for the application: from refreshing some graphics to storing the location data internally for any further use. The listener is as follows:
The displayLocation function is where the logic associated with the location change resides. Here’s the minimal code you need:
Considerations about Location Updates
In a call to the LocationManager to start getting updates you pass a few parameters. The first parameter is the name of the location provider (GPS or NETWORK) you want to use. The last parameter is the listener being called back whenever the location changes. In the middle, there are two integers both set to 0 in the previous code snippet. What are they all about?
The first integer indicates the minimum frequency of notification in milliseconds. By leaving the value set to 0 you in fact receive updates constantly. The second integer refers to the minimum distance between two successive detections that is enough for the callback to be invoked. The number here refers to meters. As you can see, by leaving both values to 0 you seriously risk to consume too much power. More specifically, 1 minute (60000 milliseconds) is considered by Google the threshold value: you should really have a good reason to use values less than that.
In many common scenarios all you want to do is placing on-demand requests: you query for the user location, you get latitude and longitude, you use them and that’s it—nothing more happens until you make another request. For things to go this way, however, you need to either use a very large value for the frequency of notifications or just stop notification after you acquired the user location. To stop getting location updates, you call another method on the Location Manager object:
In alternative you can also call requestSingleUpdate to a given provider and listener.
Using Map Views
Once you have location information a very likely thing you want to do is showing that location on a map. In Android, this means linking the Google Maps library to the project, getting a personal API key to use the library and finally using the MapView widget within a specific activity class. Let’s start to explore the changes you need to make to your manifest file:
Within the application node, you add a uses-library entry that points to Android Maps library. In addition to this, you also need to add the corresponding JAR file to the project using the steps that your IDE (whether Eclipse or IntelliJ) require.
The XML layout now includes a MapView widget as shown below:
As you can see, the MapView requires an API key that you need to get for each certificate you use to sign your Android applications. To be able to publish Android applications, you need to first sign them with a digital certificate. These certificates can be generated using the tools in the Android SDK and will just be added to the build process of your IDE. In the end, once you get the certificate compilation and signing is automatically achieved by the IDE.
In order to get the API key, you first need to acquire a hash from the certificate. The tool that does this for you is keytool and it is located in the Java SDK directory. The tool accepts as a parameter the full path name of the certificate and output a string that is just the hash you need to get a Maps key from Google. Test applications are usually transparently signed with a debug certificate. To write test map view applications, you need a hash from this debug certificate. The following is the command line for keytool:
Everything here is a constant string except path. You should replace path with the full path to the debug certificate. On Windows machines, the debug certificate is the following file:
After running the command line tool, you get a MD5 hash string. The next step consists in opening the following page in your browser https://developers.google.com/android/maps-api-signup. Here you enter your MD5 hash string and get back the API key for using Google Maps from Android. The API key must be passed to the MapView widget.
Another interesting fact is that MapView can’t be used from within an Activity class that doesn’t inherit from MapActivity. So this become another change to make to your code:
Inheriting from MapActivity requires the override of the isRouteDisplayed method which just returns false most of the time. The MapActivity class belongs to the com.google,android.maps package. Here’s the code to interact with the MapView widget once you have a location object:
You typically set a zoom factor for the map and grab the map controller instance. If you plan to display markers then you also create a location overlay for the MapView widget. To position the map on a point, you need to transform latitude and longitude in a GeoPoint object:
The method setCenter centers the map on the given point whereas the method animateTo animates the map to move from the current point to the specified point. (See Figure 1).
Figure 1. The MapView widget in action.
Early on in the chapter I multiplied the values of latitude and longitude by 1E6. That’s required to create a GeoPoint and subsequently to operate on a MapView. Multiplying by 1E6 transforms degrees in microdegrees and that’s precisely what’s required to create successfully a GeoPoint object to work with maps.
Using location data is common and also critical in mobile applications. In Android using latitude and longitude is probably a little bit harder than in Windows Phone but probably the Android API gives you even more control over the position and the geolocation API. While you can rely on the location manager to get coordinates, you need to set up Google Maps on your Android device to display point on a graphical map.
Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...
This author has published 54 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.