Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Android Location with Google Maps - Part 3

DZone's Guide to

Android Location with Google Maps - Part 3

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

In Part 1, we analyzed our requirements and the tools at our disposal to get an initial application design.

 

 

 In Part 2, we implemented LocatorOverlay. Now we will proceed with the Location class, where most of the location-specific code will be encapsulated. The imports of interest are the various classes in the Google Maps and Android Location packages:

 

// package statement and other imports
//...
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import android.content.Context;

import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;

/**
* This class encapsulates the location logic
*/
public class Locator{

 /** Access to the phone's location services */
 LocationManager locManager;

/** Location providers */
List providers;
String bestProvider;

 /** Providers are selected based on specified criteria.*/
 Criteria criteria;

 /** utility class to manage zooming of a map.*/
 private MapController mapController;

 /** Zoom level we want, between 1 and 21 */
 private static final int ZOOM_LEVEL = 16;

 /** Overlays */
  private LocatorOverlay overlay;
  private List mapOverlays;

 /** Ctor */
  public Locator(Context ctx, MapView mapView, Criteria crit){
        mapController = mapView.getController();
     	mapController.setZoom(ZOOM_LEVEL );

	// Acquire a reference to the system Location Manager
        locManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);

        mapOverlays = mapView.getOverlays();
        // our locator icon in the res/drawable folder
        Drawable drawable = ctx.getResources().getDrawable(R.drawable.icon);
        overlay =  new LocatorOverlay(drawable, ctx);

        // List all providers
     	providers = locManager.getAllProviders();

     	if(crit == null) {
     	// No arg Ctor means The new object will have no requirements on accuracy, 
        // power, or response time; will not require altitude, speed, or bearing;
     	// and will not allow monetary cost
     	    criteria = new Criteria();
     	}
     	else{
     		criteria = crit;
     	}  
       // get the best provider for the criteria we have  
       bestProvider = locManager.getBestProvider(criteria, false);

    }

  /***/
  public List listAllProviders(){
    return providers;
  }

  /***/
  public String getBestProvider(){
    return bestProvider;
  }

  /***/
  public Location getLastKnownLocation(){
    return  locManager.getLastKnownLocation(bestProvider);
  }

   //... 
}

 

Nothing earth-shattering here. We are basically initializing data members we need in the Constructor and encapsulate a few of LocationManager's methods. We use our own icon in the resources drawable folder (icon.jpg) as a marker, to pinpoint the handset's location :

Are we done already? Of course not. We still need to handle location updates. So we'll need to add the following:

 

// add import
import android.location.LocationListener;

// modify class statement
public class Locator implements LocationListener { ...

// add data members
/** Control of the frequency of location update notifications */
  private static final long MIN_TIME = 20000L; // millis
  private static final float MIN_DISTANCE = 100F; // meters

// add methods
 /**
   * No updates for MIN_TIME to conserve power. 
   * No updates if device doesn't move beyond MIN_DISTANCE
   *
   * The calling thread must be a Looper thread such as 
   * the main thread of the calling Activity.
   */
  public void requestUpdates(){
    locManager.requestLocationUpdates(bestProvider, 
                                      MIN_TIME, 
                                      MIN_DISTANCE, 
                                      this); // listener
  }

  /***/
  public void removeUpdates(){
    locManager.removeUpdates(this);
  }

  // add the Listener callbacks 

  public void onStatusChanged(String provider, int status, Bundle extras) {}
  public void onProviderEnabled(String provider) {}
  public void onProviderDisabled(String provider) {}
  /**
   *  Called when a new location is found by the network location provider.
   * */
   public void onLocationChanged(Location location) {
      //TODO	
   }

 

Notice how the method requestUpdates() needs a LocationListener (i.e. the current object, now that it implements the interface). But the most interesting method is the last one. This is where we would get the new location, center the map around it, and add a number of overlays. To go from an android.location point to a Google Map one, we need to transition from the Location object where coordinates are of type double, to the Google Map GeoPoint one, which stores them as integers of micro degrees:

 

public void onLocationChanged(Location location) {
    int lat = (int) (location.getLatitude() * 1E6);
    int lng = (int) (location.getLongitude() * 1E6);
    GeoPoint point = new GeoPoint(lat, lng);
    mapController.setCenter(point);

    // overlays
    OverlayItem overlayitem = new OverlayItem(point, "Location Provider: " 
                                 + bestProvider, "Accuracy: "
                                 + getLastKnownLocation().getAccuracy() 
                                 + " meters" );
    overlay.addOverlay(overlayitem);
    mapOverlays.add(overlay);
}

 

This is where we enter the overlay items we want for the LocatorOverlay class to process. Here, we only added one overlay item: the default location provider (i.e. network) along with its associated accuracy. There are providers with better precision (like GPS), at the price of increased battery consumption.

 

 

That's basically it. We are now ready to tackle the last part, the UI with LocatorActivity...in Part 4.

 

From Tony's Blog

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}