You are currently browsing the monthly archive for April 2012.

I have been trying this for a month and a lot of my readers asked to write a tutorial that makes it easy to draw a line on Google Maps for Android between two locations. I have gone through a lot of material. Most of the articles on this exact issue are not exactly addressing this specific issue. So their code is way too complex for this simple task. I have tried to make this as simple as possible.

Assumption About The Reader:

At this point I assume that reader of this article have already configured everything and Google Maps are displayed in their emulator properly. For those who don’t have Google Maps properly displayed in their emulator, they can read my earlier articles. Links provided at the end of this article.

Objective:

Draw a line that between two points on Google Maps lets say City “A” and City “B”. Repeat the process to draw a line between City “B” and City “C”.

What we need:

Coordinates of 3 cities or any 3 locations that we want to connect.

  1. Abbottabad :   34159000,73220000
  2. Islamabad :      33695043,73050000
  3. Rawalpindi :    33615043, 73050000

I have taken relative coordinates of 3 Pakistani cities starting from Abbottabad (where my family lives), moving to Islamabad (Capital of Pakistan). From Islamabad moving to Rawalpindi.

Coding (the part everyone’s been waiting for):

Create an overlay class lets say by the name of MyOverlay inside our main activity class named “GoogleMapsDrawPath” that extends MapActivity


class MyOverlay extends Overlay{

public MyOverlay(){

}

public void draw(Canvas canvas, MapView mapv, boolean shadow){
 super.draw(canvas, mapv, shadow);

//Configuring the paint brush

Paint mPaint = new Paint();
 mPaint.setDither(true);
 mPaint.setColor(Color.RED);
 mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
 mPaint.setStrokeJoin(Paint.Join.ROUND);
 mPaint.setStrokeCap(Paint.Cap.ROUND);
 mPaint.setStrokeWidth(4);

 GeoPoint gP1 = new GeoPoint(34159000,73220000);//starting point Abbottabad
 GeoPoint gP2 = new GeoPoint(33695043,73050000);//End point Islamabad

 GeoPoint gP4 = new GeoPoint(33695043, 73050000);//Start point Islamabad
 GeoPoint gP3 = new GeoPoint(33615043, 73050000);//End Point Rawalpindi

Point p1 = new Point();
 Point p2 = new Point();
 Path path1 = new Path();

 Point p3 = new Point();
 Point p4 = new Point();
 Path path2 = new Path();
 projection.toPixels(gP2, p3);
 projection.toPixels(gP1, p4);

path1.moveTo(p4.x, p4.y);//Moving to Abbottabad location
 path1.lineTo(p3.x,p3.y);//Path till Islamabad

 projection.toPixels(gP3, p1);
 projection.toPixels(gP4, p2);

path2.moveTo(p2.x, p2.y);//Moving to Islamabad location
 path2.lineTo(p1.x,p1.y);//Path to Rawalpindi

 canvas.drawPath(path1, mPaint);//Actually drawing the path from Abbottabad to Islamabad
 canvas.drawPath(path2, mPaint);//Actually drawing the path from Islamabad to Rawalpindi

 }

}

Explanation:

The code is pretty self explanatory as I have commented the parts that required explanation. First we configure the paint brush. To draw a line between two points we need to have coordinates of  at least two locations but as I am connecting 3 locations, I have taken 4 GeoPoints , repeating the coordinates of  Islamabad. I have done this to demonstrate that each time we draw a line we will need two points. After that I have created 4 Points and 2 Paths. Than setting the Projection. In simple words associating the GeoPoints  to Points.  After this setting the Paths like moving it to a starting location and defining the end point of the Path. Lastly call the canvas.drawPath(path1, mPaint) method providing it the path and the brush to actually draw the line on the map.

Configuring the Main Activity Class:

Add the following code in the onCreate method of GoogleMapsDrawPath class.


mapView = (MapView) findViewById(R.id.mapview1);//Creating an instance of MapView
 mapView.setBuiltInZoomControls(true);//Enabling the built-in Zoom Controls

 gP = new GeoPoint(33695043, 73000000);//Creating a GeoPoint

 mc = mapView.getController();
 mc.setCenter(gP);
 mc.setZoom(9);//Initializing the MapController and setting the map to center at the
 //defined GeoPoint

mapOverlays = mapView.getOverlays();
 projection = mapView.getProjection();

 myoverlay = new MyOverlay();
 mapOverlays.add(myoverlay);

Explanation:

Create instance of the mapView, enable the built-in zoom controls. Create GeoPoints and move the map to center at the created GeoPoint. Lastly add overlays from the myOverlay class to the map.

Path starting from Abbottabad moving towards Islamabad

Path Reaching Islamabad and than the second Path Starting from Islamabad to Rawalpindi

Complete path starting from Abbottabad to Rawalpindi. It looks like one single line but actually it consists of two line. The second one starting from the point where the first one is ending.

Some Extras that need explanation:

I feel the need of explaining a few more things that even if we don’t understand the code will work. But the readers have the right to know why a certain method, object, class etc is used.

  • GeoPoint :An immutable class representing a pair of latitude and longitude, stored as integer numbers of microdegrees
  • Projection :A Projection serves to translate between the coordinate system of x/y on-screen pixel coordinates and that of latitude/longitude points on the surface of the earth.
  • Point :Converts the given GeoPoint to onscreen pixel coordinates, relative to the top-left of the MapView that provided this Projection

 

Complete Code for GoogleMapsDrawPath Application:


package com.android.googlemapsdrawpath;

import java.util.List;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Bundle;

public class GoogleMapsDrawPath extends MapActivity {
 /** Called when the activity is first created. */
 private List mapOverlays;
 private Projection projection;
 private MapController mc;
 private MapView mapView;
 private GeoPoint gP;
 //private GeoPoint gP2;
 private MyOverlay myoverlay;

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

 mapView = (MapView) findViewById(R.id.mapview1);//Creating an instance of MapView
 mapView.setBuiltInZoomControls(true);//Enabling the built-in Zoom Controls

 gP = new GeoPoint(33695043, 73000000);//Creating a GeoPoint

 mc = mapView.getController();
 mc.setCenter(gP);
 mc.setZoom(9);//Initializing the MapController and setting the map to center at the
 //defined GeoPoint

mapOverlays = mapView.getOverlays();
 projection = mapView.getProjection();

 myoverlay = new MyOverlay();
 mapOverlays.add(myoverlay);

 }

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

 class MyOverlay extends Overlay{

public MyOverlay(){

}

public void draw(Canvas canvas, MapView mapv, boolean shadow){
 super.draw(canvas, mapv, shadow);
 //Configuring the paint brush
 Paint mPaint = new Paint();
 mPaint.setDither(true);
 mPaint.setColor(Color.RED);
 mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
 mPaint.setStrokeJoin(Paint.Join.ROUND);
 mPaint.setStrokeCap(Paint.Cap.ROUND);
 mPaint.setStrokeWidth(4);


 GeoPoint gP1 = new GeoPoint(34159000,73220000);//starting point Abbottabad
 GeoPoint gP2 = new GeoPoint(33695043,73050000);//End point Islamabad

 GeoPoint gP4 = new GeoPoint(33695043, 73050000);//Start point Islamabad
 GeoPoint gP3 = new GeoPoint(33615043, 73050000);//End Point Rawalpindi

Point p1 = new Point();
 Point p2 = new Point();
 Path path1 = new Path();

 Point p3 = new Point();
 Point p4 = new Point();
 Path path2 = new Path();
 projection.toPixels(gP2, p3);
 projection.toPixels(gP1, p4);

path1.moveTo(p4.x, p4.y);//Moving to Abbottabad location
 path1.lineTo(p3.x,p3.y);//Path till Islamabad

 projection.toPixels(gP3, p1);
 projection.toPixels(gP4, p2);

path2.moveTo(p2.x, p2.y);//Moving to Islamabad location
 path2.lineTo(p1.x,p1.y);//Path to Rawalpindi

 canvas.drawPath(path1, mPaint);//Actually drawing the path from Abbottabad to Islamabad
 canvas.drawPath(path2, mPaint);//Actually drawing the path from Islamabad to Rawalpindi

 }

}
}

 

To get going with this tutorial I am using the code from my previous tutorial https://mirnauman.wordpress.com/2012/04/10/android-google-maps-tutorial-part-5-adding-multiple-images-to-google-maps-using-itemizedoverlay/

Objective:-

To get the Latitude and Longitude values of a location that is touched on Google Maps in Android.

Solution:-

All we need is a simple function onTouchEvent(MotionEvent event, MapView mapView), that can be added to either a Class that extends Overlay  or a Class that extends ItemizedOverlay. In my tutorial I have used ItemizedOverlay so I ll add the function to my class “MirItemizedOverlay” that extends ItemizedOverlay.

Function to be added:-


@Override
 public boolean onTouchEvent(MotionEvent event, MapView mapView)
 {
 //---when user lifts his finger---
 if (event.getAction() == 1) {
 GeoPoint p = mapView.getProjection().fromPixels(
 (int) event.getX(),
 (int) event.getY());
 Toast.makeText(getBaseContext(),
 p.getLatitudeE6() / 1E6 + "," +
 p.getLongitudeE6() /1E6 ,
 Toast.LENGTH_SHORT).show();
 }
 return false;
 }

Now when we Run the Application and touch the sceen. As soon as we lift the touch, the application will display the Latitude and Longitude values in a Toast.

Latitude and Longitude of the location that is touched on the Map.

Complete code of tutorial Google Maps Part 5 will become


package com.android.googlemapsapp;

import java.util.ArrayList;
 import java.util.List;

import android.app.Activity;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import com.google.android.maps.GeoPoint;
 import com.google.android.maps.ItemizedOverlay;
 import com.google.android.maps.MapActivity;
 import com.google.android.maps.MapController;
 import com.google.android.maps.MapView;
 import com.google.android.maps.MyLocationOverlay;
 import com.google.android.maps.OverlayItem;

import android.os.Bundle;
 import android.view.MotionEvent;
 import android.widget.Toast;

public class GoogleMapsAppActivity extends MapActivity {

private MapView mapView;
 private MapController mc;
 //MyLocationOverlay myLocOverlay = 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.mapview1);
 mc = mapView.getController();
 mapView.setBuiltInZoomControls(true);

Drawable makerDefault = this.getResources().getDrawable(R.drawable.star_big_on);
 MirItemizedOverlay itemizedOverlay = new MirItemizedOverlay(makerDefault);
 GeoPoint point = new GeoPoint(33480000, 73000000);

OverlayItem overlayItem = new OverlayItem(point, "Islamabad", null);
 itemizedOverlay.addOverlayItem(33695043, 73000000, "Islamabad");
 itemizedOverlay.addOverlayItem(33480000, 73000000, "Some Other Pakistani City");
 itemizedOverlay.addOverlayItem(33380000, 73000000, "Some Other Pakistani City");

mapView.getOverlays().add(itemizedOverlay);

MapController mc = mapView.getController();
 mc.setCenter(new GeoPoint(33580000, 73000000)); // Some where near Islamabad.
 mc.zoomToSpan(itemizedOverlay.getLatSpanE6(), itemizedOverlay.getLonSpanE6());

}

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

private class MirItemizedOverlay extends ItemizedOverlay<OverlayItem> {

private List<OverlayItem> mOverlays = new ArrayList<OverlayItem>();

public MirItemizedOverlay(Drawable defaultMarker) {
 super(boundCenterBottom(defaultMarker));
 // TODO Auto-generated constructor stub
 }
 @Override
 protected OverlayItem createItem(int i) {
 return mOverlays.get(i);
 }

@Override
 public int size() {
 return mOverlays.size();
 }

public void addOverlayItem(OverlayItem overlayItem) {
 mOverlays.add(overlayItem);
 populate();
 }

public void addOverlayItem(int lat, int lon, String title) {
 GeoPoint point = new GeoPoint(lat, lon);
 OverlayItem overlayItem = new OverlayItem(point, title, null);
 addOverlayItem(overlayItem);
 }

@Override
 public boolean onTouchEvent(MotionEvent event, MapView mapView)
 {
 //---when user lifts his finger---
 if (event.getAction() == 1) {
 GeoPoint p = mapView.getProjection().fromPixels(
 (int) event.getX(),
 (int) event.getY());
 Toast.makeText(getBaseContext(),
 p.getLatitudeE6() / 1E6 + "," +
 p.getLongitudeE6() /1E6 ,
 Toast.LENGTH_SHORT).show();
 }
 return false;
 }

}

}

Dear readers am back after a long time trying to complete what i started a few months back. This article is part 5 of the previous series but it doesn’t depend on the code of the previous articles, still they can be referenced to get a better understanding of configuring Google Maps for Android and learning the basic development of Google Maps for Android. The development environment stays the same as of the previous articles. No change in any of the configurations etc.

Please see the links for previous articles for basics of Google Maps for Android.

  1. https://mirnauman.wordpress.com/2012/01/30/using-google-maps-in-android-development-tutorial-part-1/
  2. https://mirnauman.wordpress.com/2012/02/07/using-gps-in-android-and-animating-google-maps-to-the-current-gps-location-android-tutorial-part-2/
  3. https://mirnauman.wordpress.com/2012/02/13/adding-image-to-googlemaps-using-map-overlays-android-tutorial-part-3/
  4. https://mirnauman.wordpress.com/2012/02/14/android-google-maps-tutorial-part-4-adding-menu-some-additional-functionality-like-zooming-changing-map-view-animating-to-gps-current-location-using-menu-button/

Objective of this article is to add multiple images to our Google Map Application for Android. I have taken a scenario where I have a list of coordinates  of different cities of Pakistan and I want display an image on each city. Check the final output of this article so that you have an idea of what we will achieve at the end of this tutorial.

Multiple Images Displayed on our Android Google Maps Application.

Starting with the actual work,  inside the main GoogleMapsAppActivity Class that  extends MapActivity, add a Class lets say MirItemizedClass that extends ItemizedOverlay.  This is a  base class for an Overlay which consists of a list of OverlayItems. This handles sorting north-to-south for drawing, creating span bounds, drawing a marker for each point, and maintaining a focused item. It also matches screen-taps to items, and dispatches Focus-change events to an optional listener.


private class MirItemizedOverlay extends ItemizedOverlay {

 private List<OverlayItem> mOverlays = new ArrayList();

 public MirItemizedOverlay(Drawable defaultMarker) {
 super(boundCenterBottom(defaultMarker));
 // TODO Auto-generated constructor stub
 }

 @Override
 protected OverlayItem createItem(int i) {
 return mOverlays.get(i);
 }

@Override
 public int size() {
 return mOverlays.size();
 }

 public void addOverlayItem(OverlayItem overlayItem) {
 mOverlays.add(overlayItem);
 populate();
 }

 }

We have to set the bounding rectangle of the drawable  that we add to our ItemizedOverlay. The defaultMarker is a Drawable that is drawn on every OverlayItem that we add to our ItemizedOverlay. To do this we have to use boundCenterBottom or boundCenter or we can use the setBounds method to get the job done. So we have used boundCenterBottom(defaultMaker).  To add multiple overlays we have added a List of OverlayItem and used that in the createItem and size methods of our ItemizedOverlay Class. To add the OverlayItems to our internal list we have added the method addOverlayItem(OverlayItem overlayItem).

Now we will use the functionality of MirItemizedOverlay Class in the onCeate method of our main GoogleMapsAppActivity Class.

We will create instances of Drawable and MirItemizedOverlay to retrieve the image from our res/drawable folder and to supply that image to the our ItemizedOverlay Class.


Drawable makerDefault = this.getResources().getDrawable(R.drawable.star_big_on);
 MirItemizedOverlay itemizedOverlay = new MirItemizedOverlay(makerDefault);
 GeoPoint point = new GeoPoint(33480000, 73000000);

We have also ceated a GeoPoint object with a latitude, longitude value.  Add another method  to our MirItemizedOverlay Class that will take two integers and a string as parameters.


public void addOverlayItem(int lat, int lon, String title) {
 GeoPoint point = new GeoPoint(lat, lon);
 OverlayItem overlayItem = new OverlayItem(point, title, null);
 addOverlayItem(overlayItem);
 }

The code to create and add multiple locations to our itemizedOverlay object by using the recently created method is


OverlayItem overlayItem = new OverlayItem(point, "Islamabad", null);
 itemizedOverlay.addOverlayItem(33695043, 73000000, "Islamabad");
 itemizedOverlay.addOverlayItem(33480000, 73000000, "Some Other Pakistani City");
 itemizedOverlay.addOverlayItem(33380000, 73000000, "Some Other Pakistani City");

Now enable the mapView control to display the itemizedOverlay


mapView.getOverlays().add(itemizedOverlay);

Now tweek the mapView to get focused at a certain point and set the zooming level.


MapController mc = mapView.getController();
 mc.setCenter(new GeoPoint(33580000, 73000000)); // Some where near Islamabad.
 mc.zoomToSpan(itemizedOverlay.getLatSpanE6(), itemizedOverlay.getLonSpanE6());

Run the project we will get the output in the picture given above.

Complete Code of this tutorial.


package com.android.googlemapsapp;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

import android.os.Bundle;

&nbsp;

public class GoogleMapsAppActivity extends MapActivity {

 private MapView mapView;
 private MapController mc;

 /** 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.mapview1);
 mc = mapView.getController();
 mapView.setBuiltInZoomControls(true);

 Drawable makerDefault = this.getResources().getDrawable(R.drawable.star_big_on);
 MirItemizedOverlay itemizedOverlay = new MirItemizedOverlay(makerDefault);
 GeoPoint point = new GeoPoint(33480000, 73000000);

 OverlayItem overlayItem = new OverlayItem(point, "Islamabad", null);
 itemizedOverlay.addOverlayItem(33695043, 73000000, "Islamabad");
 itemizedOverlay.addOverlayItem(33480000, 73000000, "Some Other Pakistani City");
 itemizedOverlay.addOverlayItem(33380000, 73000000, "Some Other Pakistani City");

 mapView.getOverlays().add(itemizedOverlay);

 MapController mc = mapView.getController();
 mc.setCenter(new GeoPoint(33580000, 73000000)); // Some where near Islamabad.
 mc.zoomToSpan(itemizedOverlay.getLatSpanE6(), itemizedOverlay.getLonSpanE6());

}

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

 private class MirItemizedOverlay extends ItemizedOverlay {

 private List<OverlayItem> mOverlays = new ArrayList<OverlayItem>();

 public MirItemizedOverlay(Drawable defaultMarker) {
 super(boundCenterBottom(defaultMarker));
 // TODO Auto-generated constructor stub
 }
 @Override
 protected OverlayItem createItem(int i) {
 return mOverlays.get(i);
 }

@Override
 public int size() {
 return mOverlays.size();
 }

 public void addOverlayItem(OverlayItem overlayItem) {
 mOverlays.add(overlayItem);
 populate();
 }

 public void addOverlayItem(int lat, int lon, String title) {
 GeoPoint point = new GeoPoint(lat, lon);
 OverlayItem overlayItem = new OverlayItem(point, title, null);
 addOverlayItem(overlayItem);
 }
 }

}

The reason behind writing this article is that I got a new machine and I was configuring it for Android development. Everything went well but when came to the step for generating the Google Maps API Key, I got stuck when couldn’t find “debug.keystore” file at the desired location inside “.android”  folder.

.android folder without debug.keystore file

If we don’t have debug.keystore file we can’t get Google Maps API Key. To solve this issue and to get the debug.keystore file in the desired location is

  1. Open Eclipse
  2. Start a new Android project
  3. Run the project in any AVD that’s already created.

When the project is successfully RUN on the Android Virtual Device. Now go to your “.android” folder and check. You will see that the “debug.keystore” is present there.

.android folder with debug.keystore

REASON

By default the “debug.keystore” file is not created in “.android” folder. When we successfully build our first project, the “debug.keystore” file is automatically created in “.android” folder.

Now we can use it to generate our Google Maps API Key.

Related Article

https://mirnauman.wordpress.com/2012/01/26/how-to-get-google-maps-api-key-for-android-issues-and-errors-solved/

 

Blog Stats

  • 326,315 hits

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 233 other followers

%d bloggers like this: