Routing

This sample demonstrates a simple user experience for finding a route between two points by long pressing on a street to calculate a route from your location to the geocoded location resulting from your long press. Additionally, the sample demonstrates a dialog to input start and destination locations to calculate a route.

The sample contains four files: 1.RoutingSample When the user long clicks on the map, the activity will do the Routing Task and create the Routing List Fragment 2.Routing List Fragment This fragment populates the Listview (Navigation Drawer) using a custom adapter 3. RoutingDialogFragment When the user clicks on the Get Direction button on the bottom layout, a dialog box appears in which the user can enter the source and destination addresses to get the route. It uses Geocoding to convert the addresses to the points on the map which then the Routing sample uses for routing. 4. MyAdapter Custom Adapter for the ListView.

Features

  • Calculate route from your location to specified location
  • Route broken into segments
  • Support for credentials to support ArcGIS Online Network Analysis Service
  • Geocode the addresses

Sample Requirements

The Routing sample depends on the Andriod Support Library. Instructions for setting that it up prior to running the app is detailed below.

Steps

  1. Right click the sample project and select Android Tools > Add Support Library
  2. Accept packages to install and click Install
  3. Under Android Private Libraries you should see the android-support-v4.jar file library
  4. Right click the sample project and select Properties
  5. Select the Java Build Path on the left hand side then select Order and Export in the Java Build Path tabs
  6. Make sure Android Private Libraries is checked
  7. Run the application

Sample Code

/* Copyright 2014 ESRI
 *
 * All rights reserved under the copyright laws of the United States
 * and applicable international laws, treaties, and conventions.
 *
 * You may freely redistribute and use this sample code, with or
 * without modification, provided you include the original copyright
 * notice and use restrictions.
 *
 * See the use restrictions
 * http://help.arcgis.com/en/sdk/10.0/usageRestrictions.htm.
 */

package com.esri.arcgis.android.samples.routing;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.DrawerLayout;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.esri.android.map.GraphicsLayer;
import com.esri.android.map.LocationDisplayManager;
import com.esri.android.map.LocationDisplayManager.AutoPanMode;
import com.esri.android.map.MapView;
import com.esri.android.map.ags.ArcGISTiledMapServiceLayer;
import com.esri.android.map.event.OnLongPressListener;
import com.esri.android.map.event.OnSingleTapListener;
import com.esri.core.geometry.GeometryEngine;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.Polyline;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.map.Graphic;
import com.esri.core.symbol.PictureMarkerSymbol;
import com.esri.core.symbol.SimpleLineSymbol;
import com.esri.core.symbol.SimpleMarkerSymbol;
import com.esri.core.tasks.na.NAFeaturesAsFeature;
import com.esri.core.tasks.na.Route;
import com.esri.core.tasks.na.RouteDirection;
import com.esri.core.tasks.na.RouteParameters;
import com.esri.core.tasks.na.RouteResult;
import com.esri.core.tasks.na.RouteTask;
import com.esri.core.tasks.na.StopGraphic;

public class RoutingSample extends Activity implements
		RoutingListFragment.onDrawerListSelectedListener,
		RoutingDialogFragment.onGetRoute {
	public static MapView map = null;
	ArcGISTiledMapServiceLayer tileLayer;
	GraphicsLayer routeLayer, hiddenSegmentsLayer;
	// Symbol used to make route segments "invisible"
	SimpleLineSymbol segmentHider = new SimpleLineSymbol(Color.WHITE, 5);
	// Symbol used to highlight route segments
	SimpleLineSymbol segmentShower = new SimpleLineSymbol(Color.RED, 5);
	// Label showing the current direction, time, and length
	TextView directionsLabel;
	// List of the directions for the current route (used for the ListActivity)
	public static ArrayList<String> curDirections = null;
	// Current route, route summary, and gps location
	Route curRoute = null;
	String routeSummary = null;
	public static Point mLocation = null;
	// Global results variable for calculating route on separate thread
	RouteTask mRouteTask = null;
	RouteResult mResults = null;
	// Variable to hold server exception to show to user
	Exception mException = null;

	ImageView img_cancel;
	ImageView img_currLocation;
	ImageView img_getDirections;
	public static DrawerLayout mDrawerLayout;
	LocationDisplayManager ldm;
	// Handler for processing the results
	final Handler mHandler = new Handler();
	final Runnable mUpdateResults = new Runnable() {
		public void run() {
			updateUI();
		}
	};

	// Progress dialog to show when route is being calculated
	ProgressDialog dialog;
	// Spatial references used for projecting points
	final SpatialReference wm = SpatialReference.create(102100);
	final SpatialReference egs = SpatialReference.create(4326);
	// Index of the currently selected route segment (-1 = no selection)
	int selectedSegmentID = -1;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// Retrieve the map and initial extent from XML layout
		map = (MapView) findViewById(R.id.map);
		// Add tiled layer to MapView
		tileLayer = new ArcGISTiledMapServiceLayer(
				"http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
		map.addLayer(tileLayer);

		// Add the route graphic layer (shows the full route)
		routeLayer = new GraphicsLayer();
		map.addLayer(routeLayer);

		// Initialize the RouteTask
		try {
			mRouteTask = RouteTask
					.createOnlineRouteTask(
							"http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Network/USA/NAServer/Route",
							null);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		// Add the hidden segments layer (for highlighting route segments)
		hiddenSegmentsLayer = new GraphicsLayer();
		map.addLayer(hiddenSegmentsLayer);

		// Make the segmentHider symbol "invisible"
		segmentHider.setAlpha(1);
		mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		img_cancel = (ImageView) findViewById(R.id.iv_cancel);
		img_currLocation = (ImageView) findViewById(R.id.iv_myLocation);
		img_getDirections = (ImageView) findViewById(R.id.iv_getDirections);
		mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

		// Get the location display manager and start reading location. Don't
		// auto-pan
		// to center our position
		ldm = map.getLocationDisplayManager();
		ldm.setLocationListener(new MyLocationListener());
		ldm.start();
		ldm.setAutoPanMode(AutoPanMode.OFF);

		// Set the directionsLabel with initial instructions.
		directionsLabel = (TextView) findViewById(R.id.directionsLabel);
		directionsLabel.setText(getString(R.string.route_label));

		/**
		 * On single clicking the directions label, start a ListActivity to show
		 * the list of all directions for this route. Selecting one of those
		 * items will return to the map and highlight that segment.
		 * 
		 */
		directionsLabel.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				if (curDirections == null)
					return;

				mDrawerLayout.openDrawer(Gravity.END);

				String segment = directionsLabel.getText().toString();

				ListView lv = RoutingListFragment.mDrawerList;
				for (int i = 0; i < lv.getCount() - 1; i++) {
					String lv_segment = lv.getItemAtPosition(i).toString();
					if (segment.equals(lv_segment)) {
						lv.setSelection(i);
					}
				}
			}

		});
		img_cancel.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {


				clearAll();
			}
		});

		img_currLocation.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Point p = (Point) GeometryEngine.project(mLocation, egs, wm);
				map.zoomToResolution(p, 20.0);

			}
		});

		img_getDirections.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				FragmentManager fm = getFragmentManager();
				FragmentTransaction ft = fm.beginTransaction();
				RoutingDialogFragment frag_dialog = new RoutingDialogFragment();
				ft.add(frag_dialog, "Dialog");
				ft.commit();

			}
		});

		/**
		 * On single tapping the map, query for a route segment and highlight
		 * the segment and show direction summary in the label if a segment is
		 * found.
		 */
		map.setOnSingleTapListener(new OnSingleTapListener() {
			private static final long serialVersionUID = 1L;

			public void onSingleTap(float x, float y) {
				// Get all the graphics within 20 pixels the click
				int[] indexes = hiddenSegmentsLayer.getGraphicIDs(x, y, 20);
				// Hide the currently selected segment
				hiddenSegmentsLayer.updateGraphic(selectedSegmentID,
						segmentHider);

				if (indexes.length < 1) {
					// If no segments were found but there is currently a route,
					// zoom to the extent of the full route
					if (curRoute != null) {
						map.setExtent(curRoute.getEnvelope(), 250);
						directionsLabel.setText(routeSummary);
					}
					return;
				}
				// Otherwise update our currently selected segment
				selectedSegmentID = indexes[0];
				Graphic selected = hiddenSegmentsLayer
						.getGraphic(selectedSegmentID);
				// Highlight it on the map
				hiddenSegmentsLayer.updateGraphic(selectedSegmentID,
						segmentShower);
				String direction = ((String) selected.getAttributeValue("text"));
				double time = ((Double) selected.getAttributeValue("time"))
						.doubleValue();
				double length = ((Double) selected.getAttributeValue("length"))
						.doubleValue();
				// Update the label with this direction's information
				String label = String.format("%s%n%.1f minutes (%.1f miles)",
						direction, time, length);
				directionsLabel.setText(label);
				// Zoom to the extent of that segment
				map.setExtent(selected.getGeometry(), 50);
			}

		});

		/**
		 * On long pressing the map view, route from our current location to the
		 * pressed location.
		 * 
		 */
		map.setOnLongPressListener(new OnLongPressListener() {

			private static final long serialVersionUID = 1L;

			public boolean onLongPress(final float x, final float y) {
				final Point loc = map.toMapPoint(x, y);

				Point p = (Point) GeometryEngine.project(loc, wm, egs);

				clearAll();
				QueryDirections(mLocation, p);
				return true;
			}

		});
	}

	private void QueryDirections(final Point mLocation, final Point p) {

		// Show that the route is calculating
		dialog = ProgressDialog.show(RoutingSample.this, "Routing Sample",
				"Calculating route...", true);
		// Spawn the request off in a new thread to keep UI responsive
		Thread t = new Thread() {
			@Override
			public void run() {
				try {
					// Start building up routing parameters
					RouteParameters rp = mRouteTask
							.retrieveDefaultRouteTaskParameters();
					NAFeaturesAsFeature rfaf = new NAFeaturesAsFeature();
					// Convert point to EGS (decimal degrees)
					// Create the stop points (start at our location, go
					// to pressed location)
					StopGraphic point1 = new StopGraphic(mLocation);
					StopGraphic point2 = new StopGraphic(p);
					rfaf.setFeatures(new Graphic[] { point1, point2 });
					rfaf.setCompressedRequest(true);
					rp.setStops(rfaf);
					// Set the routing service output SR to our map
					// service's SR
					rp.setOutSpatialReference(wm);

					// Solve the route and use the results to update UI
					// when received
					mResults = mRouteTask.solve(rp);
					mHandler.post(mUpdateResults);
				} catch (Exception e) {
					mException = e;
					mHandler.post(mUpdateResults);
				}
			}
		};
		// Start the operation
		t.start();

	}

	/**
	 * Updates the UI after a successful rest response has been received.
	 */
	void updateUI() {
		dialog.dismiss();

		if (mResults == null) {
			Toast.makeText(RoutingSample.this, mException.toString(),
					Toast.LENGTH_LONG).show();
			curDirections = null;
			return;
		}

		// Creating a fragment if it has not been created
		FragmentManager fm = getFragmentManager();
		if (fm.findFragmentByTag("Nav Drawer") == null) {
			FragmentTransaction ft = fm.beginTransaction();
			RoutingListFragment frag = new RoutingListFragment();
			ft.add(frag, "Nav Drawer");
			ft.commit();
		} else {
			FragmentTransaction ft = fm.beginTransaction();
			ft.remove(fm.findFragmentByTag("Nav Drawer"));
			RoutingListFragment frag = new RoutingListFragment();
			ft.add(frag, "Nav Drawer");
			ft.commit();
		}

		// Unlock the NAvigation Drawer
		mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);

		// Making visible the cancel icon
		img_cancel.setVisibility(View.VISIBLE);

		curRoute = mResults.getRoutes().get(0);
		// Symbols for the route and the destination (blue line, checker flag)
		SimpleLineSymbol routeSymbol = new SimpleLineSymbol(Color.BLUE, 3);
		PictureMarkerSymbol destinationSymbol = new PictureMarkerSymbol(
				map.getContext(), getResources().getDrawable(
						R.drawable.ic_action_place));

		// Add all the route segments with their relevant information to the
		// hiddenSegmentsLayer, and add the direction information to the list
		// of directions
		for (RouteDirection rd : curRoute.getRoutingDirections()) {
			HashMap<String, Object> attribs = new HashMap<String, Object>();
			attribs.put("text", rd.getText());
			attribs.put("time", Double.valueOf(rd.getMinutes()));
			attribs.put("length", Double.valueOf(rd.getLength()));
			curDirections.add(String.format("%s%n%.1f minutes (%.1f miles)",
					rd.getText(), rd.getMinutes(), rd.getLength()));
			Graphic routeGraphic = new Graphic(rd.getGeometry(), segmentHider,
					attribs);
			hiddenSegmentsLayer.addGraphic(routeGraphic);
		}
		// Reset the selected segment
		selectedSegmentID = -1;

		// Add the full route graphics, start and destination graphic to the
		// routeLayer
		Graphic routeGraphic = new Graphic(curRoute.getRouteGraphic()
				.getGeometry(), routeSymbol);
		Graphic endGraphic = new Graphic(
				((Polyline) routeGraphic.getGeometry()).getPoint(((Polyline) routeGraphic
						.getGeometry()).getPointCount() - 1), destinationSymbol);
		routeLayer.addGraphics(new Graphic[] { routeGraphic, endGraphic });
		// Get the full route summary and set it as our current label
		routeSummary = String.format("%s%n%.1f minutes (%.1f miles)",
				curRoute.getRouteName(), curRoute.getTotalMinutes(),
				curRoute.getTotalMiles());

		directionsLabel.setText(routeSummary);
		// Zoom to the extent of the entire route with a padding
		map.setExtent(curRoute.getEnvelope(), 250);

		// Replacing the first and last direction segments
		curDirections.remove(0);
		curDirections.add(0, "My Location");

		curDirections.remove(curDirections.size() - 1);
		curDirections.add("Destination");
	}

	private class MyLocationListener implements LocationListener {

		public MyLocationListener() {
			super();
		}

		/**
		 * If location changes, update our current location. If being found for
		 * the first time, zoom to our current position with a resolution of 20
		 */
		public void onLocationChanged(Location loc) {
			if (loc == null)
				return;
			boolean zoomToMe = (mLocation == null) ? true : false;
			mLocation = new Point(loc.getLongitude(), loc.getLatitude());
			if (zoomToMe) {
				Point p = (Point) GeometryEngine.project(mLocation, egs, wm);
				map.zoomToResolution(p, 20.0);
			}
		}

		public void onProviderDisabled(String provider) {
			Toast.makeText(getApplicationContext(), "GPS Disabled",
					Toast.LENGTH_SHORT).show();
		}

		public void onProviderEnabled(String provider) {
			Toast.makeText(getApplicationContext(), "GPS Enabled",
					Toast.LENGTH_SHORT).show();
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

	}

	@Override
	protected void onPause() {
		super.onPause();
		map.pause();
	}

	@Override
	protected void onResume() {
		super.onResume();
		map.unpause();
	}

	/*
	 * When the user selects the segment from the listview, it gets highlighted
	 * on the map
	 */
	@Override
	public void onSegmentSelected(String segment) {

		if (segment == null)
			return;
		// Look for the graphic that corresponds to this direction
		for (int index : hiddenSegmentsLayer.getGraphicIDs()) {
			Graphic g = hiddenSegmentsLayer.getGraphic(index);
			if (segment.contains((String) g.getAttributeValue("text"))) {
				// When found, hide the currently selected, show the new
				// selection
				hiddenSegmentsLayer.updateGraphic(selectedSegmentID,
						segmentHider);
				hiddenSegmentsLayer.updateGraphic(index, segmentShower);
				selectedSegmentID = index;
				// Update label with information for that direction
				directionsLabel.setText(segment);
				// Zoom to the extent of that segment
				map.setExtent(hiddenSegmentsLayer.getGraphic(selectedSegmentID)
						.getGeometry(), 50);
				break;
			}
		}

	}

	@Override
	public void onDialogRouteClicked(Point p1, Point p2) {

		FragmentManager fm = getFragmentManager();
		FragmentTransaction ft = fm.beginTransaction();
		ft.remove(fm.findFragmentByTag("Dialog")).commit();

		Point p_start = (Point) GeometryEngine.project(p1, wm, egs);
		Point p_dest = (Point) GeometryEngine.project(p2, wm, egs);

		clearAll();

		// Adding the symbol for start point
		SimpleMarkerSymbol startSymbol = new SimpleMarkerSymbol(Color.DKGRAY,
				15, SimpleMarkerSymbol.STYLE.CIRCLE);
		Graphic gStart = new Graphic(p1, startSymbol);
		routeLayer.addGraphic(gStart);

		QueryDirections(p_start, p_dest);

	}

	/*
	 * Clear the graphics and empty the directions list
	 */

	public void clearAll() {
		
		//Removing the graphics from the layer
		routeLayer.removeAll();
		hiddenSegmentsLayer.removeAll();
		
		curDirections = new ArrayList<String>();
		mResults = null;
		curRoute = null;
		
		//Setting to default text
		directionsLabel.setText(getString(R.string.route_label));
		
		//Locking the Drawer
		mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
		
		//Removing the cancel icon
		img_cancel.setVisibility(View.GONE);

		//Removing the RoutingListFragment if present
		FragmentManager fm = getFragmentManager();
		if (fm.findFragmentByTag("Nav Drawer") != null) {
			FragmentTransaction ft = fm.beginTransaction();
			ft.remove(fm.findFragmentByTag("Nav Drawer"));
			ft.commit();
		}

	}

}
package com.esri.arcgis.android.samples.routing;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;

/*
 * This fragment populates the Navigation Drawer with
 * a customized listview and also provides the interface 
 * for communicating with the activity.
 */
public class RoutingListFragment extends Fragment implements
		ListView.OnItemClickListener, TextToSpeech.OnInitListener {
	public static ListView mDrawerList;
	onDrawerListSelectedListener mCallback;
	private TextToSpeech tts;
	private boolean isSoundOn = true;

	// Container Activity must implement this interface
	public interface onDrawerListSelectedListener {
		public void onSegmentSelected(String segment);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	@Override
	public void onAttach(Activity activity) {

		super.onAttach(activity);

		try {
			mCallback = (onDrawerListSelectedListener) activity;
		} catch (ClassCastException e) {
			throw new ClassCastException(activity.toString()
					+ " must implement onDrawerListSelectedListener");
		}

		setHasOptionsMenu(true);

	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		tts = new TextToSpeech(getActivity(), this);

		MyAdapter adapter = new MyAdapter(getActivity(),
				RoutingSample.curDirections);
		mDrawerList = (ListView) getActivity().findViewById(R.id.right_drawer);

		mDrawerList.setAdapter(adapter);
		mDrawerList.setOnItemClickListener(this);

		Switch sound_toggle = (Switch) getActivity().findViewById(R.id.switch1);
		sound_toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				isSoundOn = isChecked;
			}
		});

	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		TextView segment = (TextView) view.findViewById(R.id.segment);
		RoutingSample.mDrawerLayout.closeDrawers();
		if (isSoundOn)
			speakOut(segment.getText().toString());
		mCallback.onSegmentSelected(segment.getText().toString());
	}

	private void speakOut(String text) {
		tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		inflater.inflate(R.menu.action_layout, menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.direction:
			if (RoutingSample.mDrawerLayout.isDrawerOpen(Gravity.END)) {
				RoutingSample.mDrawerLayout.closeDrawers();
			} else {
				RoutingSample.mDrawerLayout.openDrawer(Gravity.END);
			}
			return true;

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@Override
	public void onInit(int status) {

	}

	@Override
	public void onStop() {
		super.onStop();
		tts.shutdown();

	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}
}
package com.esri.arcgis.android.samples.routing;

import java.util.List;

import android.app.Activity;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.esri.core.geometry.GeometryEngine;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.tasks.geocode.Locator;
import com.esri.core.tasks.geocode.LocatorFindParameters;
import com.esri.core.tasks.geocode.LocatorGeocodeResult;

/*
 * This fragment displays a dialog box which contains text fields for source and destination addresses.
 * It also contains two icons "My Location" and "Swap Addresses". When user clicks on My Location icon, the focused
 * text field displays the text "My Location". When "Swap Addresses" icon is clicked the addresses in the text boxes are swapped.
 * When the user clicks on the "Route" button, the addresses are geocoded to points which are then used by the RoutingSample activity to
 * display the route.
 * 
 */

public class RoutingDialogFragment extends DialogFragment implements
		OnFocusChangeListener, OnClickListener {

	EditText et_source;
	EditText et_destination;
	Locator locator;
	static ProgressDialog dialog;
	static Handler handler;
	Button bGetRoute;

	// For storing the result of Geocoding Task
	List<LocatorGeocodeResult> result_origin = null;
	List<LocatorGeocodeResult> result_destination = null;

	// Interface to be implemented by the activity
	onGetRoute mCallback;

	// To check if the edit text contains "My Location"
	boolean src_isMyLocation = false;
	boolean dest_isMyLocation = false;

	final SpatialReference wm = SpatialReference.create(102100);
	final SpatialReference egs = SpatialReference.create(4326);
	String source;
	String destination;
	// Image views for the icons
	ImageView img_sCancel, img_dCancel, img_myLocaion, img_swap;

	// Runnable to dismiss the process dialog
	static public class MyRunnable implements Runnable {
		public void run() {
			dialog.dismiss();
		}
	}

	// Interface
	public interface onGetRoute {
		public void onDialogRouteClicked(Point p1, Point p2);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		handler = new Handler();
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		try {
			mCallback = (onGetRoute) activity;
		} catch (ClassCastException e) {
			throw new ClassCastException(activity.toString()
					+ " must implement onDrawerListSelectedListener");
		}

	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.dialog_layout, container);

		// Set the views from the XML layout
		et_source = (EditText) view.findViewById(R.id.et_source);
		et_destination = (EditText) view.findViewById(R.id.et_destination);
		img_sCancel = (ImageView) view.findViewById(R.id.iv_cancelSource);
		img_dCancel = (ImageView) view.findViewById(R.id.iv_cancelDestination);
		img_swap = (ImageView) view.findViewById(R.id.iv_interchange);
		img_myLocaion = (ImageView) view.findViewById(R.id.iv_myDialogLocation);
		bGetRoute = (Button) view.findViewById(R.id.bGetRoute);

		// Adding custom Listener to edit text views
		et_source.addTextChangedListener(new MyTextWatcher(et_source));
		et_destination
				.addTextChangedListener(new MyTextWatcher(et_destination));

		// Adding Focus Change listener to the edit text views
		et_source.setOnFocusChangeListener(this);
		et_destination.setOnFocusChangeListener(this);

		// Setting onClick listener for the icons on the dialog
		img_dCancel.setOnClickListener(this);
		img_sCancel.setOnClickListener(this);
		img_swap.setOnClickListener(this);
		img_myLocaion.setOnClickListener(this);

		// Adding onClick listener for the button
		bGetRoute.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				source = et_source.getText().toString();
				destination = et_destination.getText().toString();

				// If either of the edit text is empty, display the toast
				if (source.equals("") || destination.equals("")) {
					Toast.makeText(getActivity(), "Place cannot be empty",
							Toast.LENGTH_LONG).show();
					return;
				}

				// Checking if the edit text views contain "My Location"
				if (source.equals("My Location"))
					src_isMyLocation = true;
				if (destination.equals("My Location"))
					dest_isMyLocation = true;

				// If source and destination are not same then geocode the
				// addresses
				if (!source.equals(destination)) {
					// Geocode the addresses
					geocode(source, destination);
				} else {
					Toast.makeText(getActivity(),
							"Source and Destination should be different",
							Toast.LENGTH_LONG).show();
				}

			}
		});

		// Removing title from the dialog box
		getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);

		return view;
	}

	private void geocode(String address1, String address2) {
		try {
			// create Locator parameters from single line address string
			LocatorFindParameters findParams_source = new LocatorFindParameters(
					address1);
			// set the search country to USA
			findParams_source.setSourceCountry("USA");
			// limit the results to 2
			findParams_source.setMaxLocations(2);
			// set address spatial reference to match map
			findParams_source.setOutSR(RoutingSample.map.getSpatialReference());
			// execute async task to geocode address

			LocatorFindParameters findParams_dest = new LocatorFindParameters(
					address2);
			findParams_dest.setSourceCountry("USA");
			findParams_dest.setMaxLocations(2);
			findParams_dest.setOutSR(RoutingSample.map.getSpatialReference());

			Geocoder gcoder = new Geocoder(findParams_source, findParams_dest);
			gcoder.execute();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private class Geocoder extends AsyncTask<Void, Void, Void> {

		// Location Find Parameters for both source and destination addresses
		LocatorFindParameters lfp_start, lfp_dest;

		// Constructor
		public Geocoder(LocatorFindParameters findParams_start,
				LocatorFindParameters findParams_dest) {
			lfp_start = findParams_start;
			lfp_dest = findParams_dest;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			// Displaying the Process Dialog
			dialog = ProgressDialog.show(getActivity(), "Routing Sample",
					"Geocoding the addresses ...");

		}

		@Override
		protected Void doInBackground(Void... params) {

			// set the geocode service

			locator = Locator.createOnlineLocator(getResources().getString(
					R.string.geocode_url));
			try {
				// pass address to find method to return point representing
				// address
				if (!src_isMyLocation)
					result_origin = locator.find(lfp_start);
				if (!dest_isMyLocation)
					result_destination = locator.find(lfp_dest);

			} catch (Exception e) {
				e.printStackTrace();
			}

			return null;
		}

		// The result of geocode task is passed as a parameter to map the
		// results

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);

			handler.post(new MyRunnable());
			Point p1 = null;
			Point p2 = null;

			// Projecting the current location to the output spatial ref
			Point currLocation = (Point) GeometryEngine.project(
					RoutingSample.mLocation, egs, wm);

			// Assignign current location to the field with value as
			// "My Location"
			if (src_isMyLocation)
				p1 = currLocation;
			else if (result_origin.size() > 0)
				p1 = result_origin.get(0).getLocation();

			if (dest_isMyLocation)
				p2 = currLocation;
			else if (result_destination.size() > 0)
				p2 = result_destination.get(0).getLocation();

			if (p1 == null) {
				Toast.makeText(getActivity(), "Not a valid source address",
						Toast.LENGTH_LONG).show();
			} else if (p2 == null) {
				Toast.makeText(getActivity(),
						"Not a valid destination address", Toast.LENGTH_LONG)
						.show();
			} else
				mCallback.onDialogRouteClicked(p1, p2);

		}
	}

	@Override
	public void onStop() {
		super.onStop();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();

	}

	// Custom Listener for the Edit text views
	private class MyTextWatcher implements TextWatcher {

		private View view;

		private MyTextWatcher(View view) {
			this.view = view;
		}

		public void beforeTextChanged(CharSequence charSequence, int i, int i1,
				int i2) {
		}

		public void onTextChanged(CharSequence charSequence, int i, int i1,
				int i2) {
		}

		public void afterTextChanged(Editable editable) {

			// Displaying the cross icon when the edit text views are not empty
			String text = editable.toString();
			switch (view.getId()) {
			case R.id.et_source:
				if (text.length() > 0)
					img_sCancel.setVisibility(View.VISIBLE);
				else
					img_sCancel.setVisibility(View.INVISIBLE);
				break;
			case R.id.et_destination:
				if (text.length() > 0)
					img_dCancel.setVisibility(View.VISIBLE);
				else
					img_dCancel.setVisibility(View.INVISIBLE);

				break;
			}
		}
	}

	@Override
	public void onFocusChange(View v, boolean hasFocus) {

		// Checking the focus of the edit text and displaying the cross icon if
		// it is not empty
		switch (v.getId()) {
		case R.id.et_source:
			if (hasFocus && et_source.getText().toString().length() > 0)
				img_sCancel.setVisibility(View.VISIBLE);
			else
				img_sCancel.setVisibility(View.INVISIBLE);
			break;
		case R.id.et_destination:
			if (hasFocus && et_destination.getText().toString().length() > 0)
				img_dCancel.setVisibility(View.VISIBLE);
			else
				img_dCancel.setVisibility(View.INVISIBLE);

			break;
		}
	}

	// OnClick events for the icons on the dialog box
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.iv_cancelSource:
			// Clearing the text
			et_source.getText().clear();
			break;
		case R.id.iv_cancelDestination:
			// Clearing the text
			et_destination.getText().clear();
			break;
		case R.id.iv_myDialogLocation:

			// Putting "My Location" in the edit text that is in focus
			if (et_source.hasFocus())
				et_source.setText("My Location");
			else
				et_destination.setText("My Location");
			break;
		case R.id.iv_interchange:

			// Swapping the values
			String temp = et_source.getText().toString();
			et_source.setText(et_destination.getText().toString());
			et_destination.setText(temp);
			break;

		}

	}

}
package com.esri.arcgis.android.samples.routing;

import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/*
 * Custom Adapter for the list view
 * 
 */
public class MyAdapter extends ArrayAdapter<String> {

	Context context;
	ArrayList<String> directions;

	MyAdapter(Context c, ArrayList<String> currDirections) {
		super(c, R.layout.list_item, R.id.segment, currDirections);
		this.context = c;
		directions = currDirections;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View row = inflater.inflate(R.layout.list_item, parent, false);
		ImageView myImage = (ImageView) row.findViewById(R.id.imageView1);

		String segment = directions.get(position);

		//For segment icons on the list.
		if (segment.contains("left")) {
			myImage.setImageResource(R.drawable.nav_left);

		} else if (segment.contains("right")) {
			myImage.setImageResource(R.drawable.nav_right);

		} else if (segment.contains("Continue") || segment.contains("straight")
				|| segment.contains("Go")) {
			myImage.setImageResource(R.drawable.nav_straight);

		} else if (segment.contains("U-turn")) {
			myImage.setImageResource(R.drawable.nav_uturn);
		}

		//For Starting and Ending Point icons
		if (position == 0) {
			myImage.setImageResource(R.drawable.ic_action_location_found);
		}
		if (position == directions.size() - 1) {
			myImage.setImageResource(R.drawable.ic_action_place);

		}

		TextView myTitle = (TextView) row.findViewById(R.id.segment);
		myTitle.setText(segment);
		return row;
	}

}
Feedback on this topic?