Monday, 10 December 2012

Find Current Location using GPS in Android


        An Android Application GPS Locator

         (Find Current Location using GPS)


This article is targeted to a beginner who wants to implement GPS functionality and work with Google Maps API as well. Before going to the progrmming, you need to know about API Key and Key Store File.

Google Maps API key and KeyStore File

The first and foremost thing is getting a Google Maps API key. Getting one is relatively easy but it requires our application to be signed with a certificate and notify Google about Hash (MD5) fingerprint of the certificate.


Generating MD5 Key and Registering it in MAPS API
We can create a new certificate by using keytool.exe, found in bin directory of JDK installation path (C:\Program Files\Java\jdk1.7.0_01\bin).


Steps to get MD5 Key:
1. Go to your android location(C:\Documents and Settings\Tara Roy\.android) where you have set your Work Space.
2. Copy "debug.keystore" & put this file in C:\debug.keystore
3. Go 2 your command prompt(cmd)
4. Type CD C:\Documents and Settings\Tara Roy
5. Next Type like this in cmd. C:\> keytool -list -v -keystore C:\debug.keystore
6. Put password ""android""
7. You will get like this...



9. Put Your MD5 Key( 28:89:52:AA:BD:53:01:90:32:F7:93:27:34:85:2F:AF ).
10. Register after giving your mail-id.
11. Success(Page will look like this)

Thank you for signing up for an Android Maps API key!
Your key is:
0uG1kA1mLxMHCVq8ArHf3eYNX8isA19dNZXSYHg
This key will work for all apps signed with your certificate whose fingerprint is:
FC:7A:5D:8D:E2:83:E9:68:31:CF:06:50:57:5E:EC:ED
Here is a sample xml layout to get you started on your way to mapping glory:
              <com.google.android.maps.MapView
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent"
                 android:apiKey="0uG1kA1mLxMHCVq8ArHf3eYNX8isA19dNZXSYHg"
                 />
           
        

Creating Application
Next:  Create a new Android Project and provide the details as below,…. 




Click Finish and the project is created. Create a Run Configuration for the project to launch an AVD targeted to Google APIs.


Try running the project with the specified configuration and it should show something like:


Before you can start using MapView control from Google APIs, you need to add the Google Maps External Library (com.google.android.map) to the library. For adding a library to the project use uses-library tag. This tag needs to be added to AndroidManifest.xml. Apart from the library, you need to add relevant permissions as well. For adding permissions, we use uses-permission tag. For our application, we will add the following permissions:
·         android.permission.ACCESS_COARSE_LOCATION: Allows application to access coarse location (Cell ID, Wi-Fi etc.)
·         android.permission.ACCESS_FINE_LOCATION: Allows application to access GPS location.
·         android.permission.INTERNET: Allows application to open network sockets.

 AndroidManifest.xml  will Look Like This:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.VertexVerveInc.GPSLocator"
    android:versionCode="1"
    android:versionName="1.0">
   
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
  <uses-permission android:name="android.permission.INTERNET" />
 
  <application android:icon="@drawable/icon" android:label="@string/app_name">
    <uses-library android:name="com.google.android.maps" />
    <activity android:name=".GPSLocatorActivity"
          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>

Add MapView control to main.xml under res/layout. The resultant code should look like:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
   
    <com.google.android.maps.MapView
              xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/present_mapview"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:clickable="true"
              android:enabled="true"
              android:apiKey="0uG1kA1mLxMHCVq8ArHf3eYNX8isA19dNZXSYHg"
    />
    </LinearLayout>

In order to display Google Map view, we need to update our Activity class (GPSLocatorActivity). This class should extend MapActivity class in place of  Activity  class. We also need to importcom.google.android.maps.MapActivity package to support  MapActivity class. We also need to overrideisRouteDisplayed method of MapActivity class. This is fairly easy, just return false from the method. After all these modifications, GPSLocatorActivity.java should look like:
import com.google.android.maps.MapActivity;
import android.os.Bundle;
 
public class GPSLocatorActivity extends MapActivity 
{
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }
  
  @Override
  protected boolean isRouteDisplayed() {
    return false;
  }
}

Out put will look like this:

Change Map view and Zoom level

We can select, if we want to show Satellite, Traffic or Street view in maps. This is simply achieved by calling setSatellite,setStreetView and setTraffic methods. Another thing to do before we move further is zoom the map a bit. Why? Because the map view shown in the above output doesn't serve any purpose. In order to set zoom level of Map, we need an instance of MapController and we can call its setZoom method. So, let's update the onCreate method ofGPSLocatorActivity class to incorporate all these changes.
mapView = (MapView) findViewById(R.id.mapView);
  
  // enable Street view by default
  mapView.setStreetView(true);
  
  // enable to show Satellite view
  // mapView.setSatellite(true);
  
  // enable to show Traffic on map
  // mapView.setTraffic(true);
  
  mapView.setBuiltInZoomControls(true);
  
  mapController = mapView.getController();
  mapController.setZoom(16); 




GPS Location Mapping

Android provides location based services through LocationManager (package android.Location) class. This class provides periodical updates about the location of the device. In order to user  LocationManager, we need to get a reference of LocationManager class by calling  getSystemService method. Later on, we need to register for location updates by calling  requestLocationUpdates method.
We need to create a class implementing abstract LocationListener class. This class will be registered with Location Manager to receive updates of location. We need to override all four methods of this class, namelyonLocationChanged,  onProviderDisabled/Enabled, and onStatusChanged. As we are just interested in getting location updates, we will modify the code of onLocationChanged to navigate to the new location received in the map view. This is achieved by calling animateTo method of MapController.
The Coding is changed and it will look like this:
public void onCreate(Bundle savedInstanceState) {
  ...
  
  locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);  
  
  locationListener = new GPSLocationListener();
  
  locationManager.requestLocationUpdates(
    LocationManager.GPS_PROVIDER, 
    0, 
    0, 
    locationListener);
  
  ...
}
 
private class GPSLocationListener implements LocationListener 
{
  @Override
  public void onLocationChanged(Location location) {
    if (location != null) {
      GeoPoint point = new GeoPoint(
          (int) (location.getLatitude() * 1E6), 
          (int) (location.getLongitude() * 1E6));
      
      Toast.makeText(getBaseContext(), 
          "Latitude: " + location.getLatitude() + 
          " Longitude: " + location.getLongitude(), 
          Toast.LENGTH_SHORT).show();
      
      mapController.animateTo(point);
      mapController.setZoom(16);
      mapView.invalidate();
    }
  }
 
  ...
}

The Out put will look like this:




Find Address for GPS Location

We can find information about an address if we know its latitude and longitude. For this purpose, we use Geocoderclass and the process is known as Geocoding. We will call getFromLocation method of the class and will pass the point as a parameter. This method returns a List of Address which contains information about address of the specified location. We can combine the information to find the complete information about the point. For this purpose, we will add a method  ConvertPointToLocation to GPSLocationListener class. ConvertPointToLocation returns astring object containing address of the location.
Code will Look Like This:
  class GPSLocationListener implements LocationListener {
  @Override
  public void onLocationChanged(Location location) {
    if (location != null) {
      ...
      String address = ConvertPointToLocation(point);
      Toast.makeText(getBaseContext(), address, Toast.LENGTH_SHORT).show();
      ...
    }
  }
 
  public String ConvertPointToLocation(GeoPoint point) {  
    String address = "";
    Geocoder geoCoder = new Geocoder(
        getBaseContext(), Locale.getDefault());
    try {
      List<Address> addresses = geoCoder.getFromLocation(
        point.getLatitudeE6()  / 1E6,
        point.getLongitudeE6() / 1E6, 1);

      if (addresses.size() > 0) {
        for (int index = 0;
            index < addresses.get(0).getMaxAddressLineIndex(); index++)
          address += addresses.get(0).getAddressLine(index) + " ";
      }
    }
    catch (IOException e) {       
      e.printStackTrace();
    }  
   
    return address;
  }




Add a Location Marker

A lot many times, we want to add a marker (image) to the location because the small circle (shown in maps by default) is sometimes useless. In order to add a marker, add a drawable resource to the project. We can import any image (which we want to use) to our project (simple drag and drop also works). Add the image to res/drawable folder.
In order to add a location marker to the map, we need to create a class which extends Overlay (com.google.android.maps package) class. We need to override draw method of the class and do some custom painting. The MapOverlay class looks like:
 class GPSLocationListener implements LocationListener
{
  @Override
  public void onLocationChanged(Location location) {
    ...
             
      mapController.animateTo(point);
      mapController.setZoom(16);
     
      // add marker
      MapOverlay mapOverlay = new MapOverlay();
      mapOverlay.setPointToDraw(point);
      List<Overlay> listOfOverlays = mapView.getOverlays();
      listOfOverlays.clear();
      listOfOverlays.add(mapOverlay);
     
      String address = ConvertPointToLocation(point);
      Toast.makeText(getBaseContext(), address, Toast.LENGTH_SHORT).show();

      ...
}

class MapOverlay extends Overlay
{
  private GeoPoint pointToDraw;

  public void setPointToDraw(GeoPoint point) {
    pointToDraw = point;
  }

  public GeoPoint getPointToDraw() {
    return pointToDraw;
  }
 
  @Override
  public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
    super.draw(canvas, mapView, shadow);          

    // convert point to pixels
    Point screenPts = new Point();
    mapView.getProjection().toPixels(pointToDraw, screenPts);

    // add marker
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.red);
    canvas.drawBitmap(bmp, screenPts.x, screenPts.y - 24, null);   
    return true;
  }
}










1 comment: