Android Open Source - advanced-tourist-map Route Calculator






From Project

Back to project page advanced-tourist-map.

License

The source code is released under:

GNU General Public License

If you think the Android project advanced-tourist-map listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2011 mapsforge.org//from  www.  j  av  a 2  s  . c  o  m
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.muxe.advancedtouristmap.routing;

import java.io.File;

import org.mapsforge.android.maps.GeoPoint;
import org.mapsforge.core.Edge;
import org.mapsforge.core.GeoCoordinate;
import org.mapsforge.core.Router;
import org.mapsforge.core.Vertex;
import org.muxe.advancedtouristmap.BaseActivity;
import org.muxe.advancedtouristmap.LocationPicker;
import org.muxe.advancedtouristmap.PositionInfo;
import org.muxe.advancedtouristmap.R;
import org.muxe.advancedtouristmap.Search;
import org.muxe.advancedtouristmap.Utility;
import org.muxe.advancedtouristmap.sourcefiles.RoutingFile;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class RouteCalculator extends BaseActivity {
  static final String TAG = RouteCalculator.class.getSimpleName();

  protected static final int INTENT_SEARCH = 0;
  protected static final int INTENT_MAP = 1;

  protected static final int START_FIELD = 0;
  protected static final int DEST_FIELD = 1;

  protected static final int DIALOG_CHOOSE_INPUT = 0;

  private static final String SAVE_START_LAT = "saved_start_lat";
  private static final String SAVE_START_LON = "saved_start_lon";
  private static final String SAVE_DEST_LAT = "saved_dest_lat";
  private static final String SAVE_DEST_LON = "saved_dest_lon";
  private static final String SAVE_RF_POSITION = "saved_dest_lon";

  GeoPoint startPoint;
  GeoPoint destPoint;

  ImageButton chooseStartButton;
  ImageButton chooseDestButton;
  private Button calcRouteButton;

  private EditText startEditText;
  private EditText destEditText;
  
  private RelativeLayout refiningPositionRow;
  private TextView refiningPositionText;
  
  int viewToSet;

  ProgressDialog progressDialog;

  private LocationManager locationManager;
  private LocationListener locationListener;
  Location currentBestLocation;

  Spinner routingFileSpinner;
  private int spinnerSelection;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("lifecycle", "routeCalculator onCreate");
    this.advancedMapViewer.setViewWithHelp(this, R.layout.activity_calculate_route);

    Intent startingIntent = getIntent();
    if (startingIntent.hasExtra("lat") && startingIntent.hasExtra("lon")) {
      this.destPoint = new GeoPoint(startingIntent.getDoubleExtra("lat", 0.0),
          startingIntent.getDoubleExtra("lon", 0.0));
    }

    this.startEditText = (EditText) findViewById(R.id.calculate_route_edittext_start);
    this.destEditText = (EditText) findViewById(R.id.calculate_route_edittext_dest);

    this.chooseStartButton = (ImageButton) findViewById(R.id.calculate_route_button_choose_start);
    this.chooseDestButton = (ImageButton) findViewById(R.id.calculate_route_button_choose_dest);
    this.calcRouteButton = (Button) findViewById(R.id.calculate_route_button_calculate);

    this.routingFileSpinner = (Spinner) findViewById(R.id.calculate_route_spinner_routing_file);
    
    this.refiningPositionRow = (RelativeLayout) findViewById(R.id.routing_loading_position);
    this.refiningPositionText = (TextView) findViewById(R.id.routing_refining_position_text);

    OnClickListener startDestChooserListener = new OnClickListener() {
      @Override
      public void onClick(View v) {
        if (v.getId() == RouteCalculator.this.chooseStartButton.getId()) {
          RouteCalculator.this.viewToSet = RouteCalculator.START_FIELD;
        } else if (v.getId() == RouteCalculator.this.chooseDestButton.getId()) {
          RouteCalculator.this.viewToSet = RouteCalculator.DEST_FIELD;
        }
        // open a dialog to select method to chose start/dest
        showDialog(DIALOG_CHOOSE_INPUT);
      }
    };

    this.chooseStartButton.setOnClickListener(startDestChooserListener);
    this.chooseDestButton.setOnClickListener(startDestChooserListener);

    this.calcRouteButton.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
        // TODO: if no routing file selected?
        // still nullpointer exception on no routing files
        RoutingFile rf = (RoutingFile) RouteCalculator.this.routingFileSpinner
            .getSelectedItem();
        if (RouteCalculator.this.startPoint == null) {
          Toast.makeText(RouteCalculator.this,
              getString(R.string.routing_no_start_selected), Toast.LENGTH_LONG)
              .show();
          return;
        }
        if (RouteCalculator.this.destPoint == null) {
          Toast.makeText(RouteCalculator.this,
              getString(R.string.routing_no_destination_selected),
              Toast.LENGTH_LONG).show();
          return;
        }
        new CalculateRouteAsync().execute(rf);
      }
    });
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == INTENT_SEARCH) {
      if (resultCode == RESULT_OK) {
        if (data != null && data.hasExtra("lon") && data.hasExtra("lat")) {
          double lon = data.getDoubleExtra("lon", 0.0);
          double lat = data.getDoubleExtra("lat", 0.0);
          GeoPoint point = new GeoPoint(lat, lon);
          if (this.viewToSet == RouteCalculator.START_FIELD) {
            this.startPoint = point;
          } else {
            this.destPoint = point;
          }
        }
      }
    } else if (requestCode == INTENT_MAP) {
      // TODO: not DRY yet
      // TODO: find nearest vertex first?
      if (resultCode == RESULT_OK) {
        if (data != null && data.hasExtra("LONGITUDE") && data.hasExtra("LATITUDE")) {
          double lon = data.getDoubleExtra("LONGITUDE", 0.0);
          double lat = data.getDoubleExtra("LATITUDE", 0.0);
          GeoPoint point = new GeoPoint(lat, lon);
          if (this.viewToSet == RouteCalculator.START_FIELD) {
            this.startPoint = point;
          } else {
            this.destPoint = point;
          }
        }
      }
    }
  }

  @Override
  protected Dialog onCreateDialog(int dialogId) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    if (dialogId == DIALOG_CHOOSE_INPUT) {
      final String[] items = getResources().getStringArray(
          R.array.routing_point_picker_values);
      final String[] items_keys = getResources().getStringArray(
          R.array.routing_point_picker_keys);
      builder.setTitle(R.string.dialog_title_find_location);
      builder.setItems(items, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int item) {
          if (items_keys[item].equals("ADDRESS")) {
            if (RouteCalculator.this.advancedMapViewer.getCurrentMapBundle()
                .isSearchable()) {
              startActivityForResult(new Intent(RouteCalculator.this,
                  Search.class), INTENT_SEARCH);
            } else {
              // TODO:
              Toast.makeText(RouteCalculator.this,
                  getString(R.string.addressfile_not_avaiable),
                  Toast.LENGTH_LONG).show();
            }
          } else if (items_keys[item].equals("POSITION")) {
            startPositionSearch();
          } else if (items_keys[item].equals("MAP")) {
            startActivityForResult(new Intent(RouteCalculator.this,
                LocationPicker.class), INTENT_MAP);
            // new Intent(RouteCalculator.this, AdvancedMapViewer.class)
            // .putExtra("mode", "LOCATION_PICKER"), INTENT_MAP);
          }
        }
      });
      return builder.create();
    }
    return null;
  }

  @Override
  protected void onResume() {
    super.onResume();
    Log.d("lifecycle", "routeCalculator onResume");

    if (this.locationManager == null) {
      this.locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    }

    if (this.startPoint != null) {
      changeStartStop(START_FIELD, this.startPoint);
      // this.startEditText.setText(this.startPoint.getLatitude() + " "
      // + this.startPoint.getLongitude());
    }
    if (this.destPoint != null) {
      changeStartStop(DEST_FIELD, this.destPoint);
      // this.destEditText.setText(this.destPoint.getLatitude() + " "
      // + this.destPoint.getLongitude());
    }

    RoutingFile[] routingFiles = this.advancedMapViewer.getCurrentMapBundle()
        .getRoutingFilesArray();

    ArrayAdapter<RoutingFile> adapter = new ArrayAdapter<RoutingFile>(this,
        android.R.layout.simple_spinner_item, routingFiles);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    this.routingFileSpinner.setAdapter(adapter);
    Log.d(TAG, "this.spinnerSelection: " + this.spinnerSelection);
    this.routingFileSpinner.setSelection(this.spinnerSelection);
  }

  void startPositionSearch() {
    // TODO: exit strategy (timer and/or when signal stabilized)
    // check if already running, if so, stop first
    if (this.locationListener != null) {
      stopPositionSearch();
    }
    
    //display animation
    this.refiningPositionRow.setVisibility(View.VISIBLE);

    // get cached locations first
    Location currentLocation;
    for (String provider : this.locationManager.getProviders(true)) {
      currentLocation = this.locationManager.getLastKnownLocation(provider);
      if (currentLocation != null) {
        if (Utility.isBetterLocation(currentLocation, this.currentBestLocation)) {
          this.currentBestLocation = currentLocation;
          changeStartStop(RouteCalculator.this.viewToSet, new GeoPoint(
              currentLocation.getLatitude(), currentLocation.getLongitude()));
          Log.d(TAG, "got better cached location from: " + provider + " ("
              + currentLocation.getAccuracy() + ")");
          RouteCalculator.this.refiningPositionText.setText(getString(R.string.refining_position) + " (" + currentLocation.getAccuracy() + " m)");
        } else {
          Log.d(TAG,
              "dismissed location from: " + provider + " ("
                  + currentLocation.getAccuracy() + ")");
        }
      }
    }

    this.locationListener = new LocationListener() {
      @Override
      public void onLocationChanged(Location location) {
        // GeoPoint point = new GeoPoint(location.getLatitude(),
        // location.getLongitude());
        if (Utility.isBetterLocation(location, RouteCalculator.this.currentBestLocation)) {
          RouteCalculator.this.currentBestLocation = location;
          Log.d(TAG, "better location from: " + location.getProvider() + " ("
              + location.getAccuracy() + ")");
          changeStartStop(RouteCalculator.this.viewToSet,
              new GeoPoint(location.getLatitude(), location.getLongitude()));
          //show accuracy in loading message
          RouteCalculator.this.refiningPositionText.setText(getString(R.string.refining_position) + " (" + location.getAccuracy() + " m)");
        } else {
          Log.d(TAG, "dismissed location from: " + location.getProvider() + " ("
              + location.getAccuracy() + ")");
        }
      }

      @Override
      public void onProviderDisabled(String provider) {

      }

      @Override
      public void onProviderEnabled(String provider) {
        // do nothing
      }

      @Override
      public void onStatusChanged(String provider, int status, Bundle extras) {
        if (status == LocationProvider.AVAILABLE) {

        } else if (status == LocationProvider.OUT_OF_SERVICE) {

        } else {
          // must be TEMPORARILY_UNAVAILABLE
        }
      }
    };

    this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0,
        this.locationListener);
    this.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0,
        this.locationListener);
  }

  @Override
  protected void onPause() {
    super.onPause();
    Log.d("lifecycle", "routeCalculator onPause");
    stopPositionSearch();
  }

  private void stopPositionSearch() {
    if (this.locationListener != null) {
      this.locationManager.removeUpdates(this.locationListener);
      this.locationListener = null;
      
      this.refiningPositionRow.setVisibility(View.GONE);
    }
  }

  void changeStartStop(int field, GeoPoint point) {
    String infoText = point.getLatitude() + " " + point.getLongitude();
    if (this.advancedMapViewer.getCurrentMapBundle().isRoutable()) {
      //TODO: may halt on slow phones
      Router router = this.advancedMapViewer.getRouter();
      if (router != null) {
        Vertex nearestVertex = router.getNearestVertex(new GeoCoordinate(point
            .getLatitude(), point.getLongitude()));
        if (nearestVertex != null) {
          infoText = PositionInfo.edgesToStringInfo(nearestVertex.getOutboundEdges());
          if (infoText.equals("")) {
            infoText = getString(R.string.positioninfo_unknown_road);
          }
        }
      }
    }

    if (field == RouteCalculator.START_FIELD) {
      this.startPoint = point;
      this.startEditText.setText(infoText);
    } else if (field == RouteCalculator.DEST_FIELD) {
      this.destPoint = point;
      this.destEditText.setText(infoText);
    }
  }

  private class CalculateRouteAsync extends AsyncTask<RoutingFile, Void, Route> {

    public CalculateRouteAsync() {
      super();
    }

    @Override
    protected void onPreExecute() {
      RouteCalculator.this.progressDialog = ProgressDialog.show(RouteCalculator.this, "",
          getString(R.string.loading_message), true);
    }

    @Override
    protected Route doInBackground(RoutingFile... routingFiles) {
      // calculate
      RoutingFile rf = null;
      try {
        rf = routingFiles[0];
      } catch (ArrayIndexOutOfBoundsException e) {
        return null;
      }

      String path = RouteCalculator.this.advancedMapViewer.getBaseBundlePath()
          + File.separator + rf.getRelativePath();
      Router router = RouteCalculator.this.advancedMapViewer.getRouter(path);
      if (router == null) {
        return null;
      }
      Vertex start = router.getNearestVertex(new GeoCoordinate(
          RouteCalculator.this.startPoint.getLatitude(),
          RouteCalculator.this.startPoint.getLongitude()));
      Vertex dest = router.getNearestVertex(new GeoCoordinate(
          RouteCalculator.this.destPoint.getLatitude(),
          RouteCalculator.this.destPoint.getLongitude()));

      if (start == null || dest == null) {
        return null;
      }

      Edge[] edges = router.getShortestPath(start.getId(), dest.getId());

      // try {
      // Thread.sleep(10000);
      // } catch (InterruptedException e) {
      //
      // }

      if (edges.length > 0) {
        Route route = new Route(edges);
        Log.d(TAG, "done");
        Log.d(TAG, "length: " + edges.length);
        return route;
      }
      return null;
    }

    @Override
    protected void onPostExecute(Route route) {
      // remove progress bar
      RouteCalculator.this.progressDialog.dismiss();
      // show route
      if (route != null) {
        RouteCalculator.this.advancedMapViewer.currentRoute = route;
        startActivity(new Intent(RouteCalculator.this, RouteList.class));
      } else {
        Log.d(TAG, "No Route Found");
        Toast.makeText(RouteCalculator.this,
            getString(R.string.routing_no_route_found), Toast.LENGTH_LONG).show();
      }
    }
  }

  @Override
  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    double startLat = savedInstanceState.getDouble(SAVE_START_LAT);
    double startLon = savedInstanceState.getDouble(SAVE_START_LON);
    double destLat = savedInstanceState.getDouble(SAVE_DEST_LAT);
    double destLon = savedInstanceState.getDouble(SAVE_DEST_LON);
    int rfPosition = savedInstanceState.getInt(SAVE_RF_POSITION, -1);
    Log.d(TAG, "rfPosition: " + rfPosition);
    if (startLat != 0.0 && startLon != 0.0) {
      this.startPoint = new GeoPoint(startLat, startLon);
    }
    if (destLat != 0.0 && destLon != 0.0) {
      this.destPoint = new GeoPoint(destLat, destLon);
    }
    if (rfPosition >= 0) {
      this.spinnerSelection = rfPosition;
    }
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    if (this.startPoint != null) {
      outState.putDouble(SAVE_START_LAT, this.startPoint.getLatitude());
      outState.putDouble(SAVE_START_LON, this.startPoint.getLongitude());
    }
    if (this.destPoint != null) {
      outState.putDouble(SAVE_DEST_LAT, this.destPoint.getLatitude());
      outState.putDouble(SAVE_DEST_LON, this.destPoint.getLongitude());
    }
    if (this.routingFileSpinner.getSelectedItemPosition() != Spinner.INVALID_POSITION) {
      Log.d(TAG, "saved Position: " + this.routingFileSpinner.getSelectedItemPosition());
      outState.putInt(SAVE_RF_POSITION, this.routingFileSpinner.getSelectedItemPosition());
    }
    super.onSaveInstanceState(outState);
  }
}




Java Source Code List

org.mapsforge.geocoding.Unchecked.java
org.mapsforge.geocoding.widget.CityCompletionAdapter.java
org.mapsforge.geocoding.widget.PlaceCompletionAdapter.java
org.mapsforge.geocoding.widget.RoadCompletionAdapter.java
org.mapsforge.geocoding.widget.RoadListAdapter.java
org.mapsforge.geocoding.widget.SqliteCompletionAdapter.java
org.mapsforge.geocoding.widget.State.java
org.muxe.advancedtouristmap.AdvancedTouristMapApplication.java
org.muxe.advancedtouristmap.AdvancedTouristMap.java
org.muxe.advancedtouristmap.BaseActivity.java
org.muxe.advancedtouristmap.CacheSizePreference.java
org.muxe.advancedtouristmap.EditPreferences.java
org.muxe.advancedtouristmap.FilePickerIconAdapter.java
org.muxe.advancedtouristmap.FilePicker.java
org.muxe.advancedtouristmap.InfoView.java
org.muxe.advancedtouristmap.LocationPicker.java
org.muxe.advancedtouristmap.MoveSpeedPreference.java
org.muxe.advancedtouristmap.PositionInfo.java
org.muxe.advancedtouristmap.Search.java
org.muxe.advancedtouristmap.SeekBarPreference.java
org.muxe.advancedtouristmap.Utility.java
org.muxe.advancedtouristmap.overlay.GenericOverlayItem.java
org.muxe.advancedtouristmap.overlay.GenericOverlay.java
org.muxe.advancedtouristmap.overlay.PoiOverlayItem.java
org.muxe.advancedtouristmap.overlay.PositionOverlayItem.java
org.muxe.advancedtouristmap.overlay.WikiOverlayItem.java
org.muxe.advancedtouristmap.poi.PoiBrowserActivity.java
org.muxe.advancedtouristmap.poi.PoiOrCategory.java
org.muxe.advancedtouristmap.routing.AngleCalc.java
org.muxe.advancedtouristmap.routing.DecisionOverlay.java
org.muxe.advancedtouristmap.routing.DecisionPoint.java
org.muxe.advancedtouristmap.routing.RouteCalculator.java
org.muxe.advancedtouristmap.routing.RouteList.java
org.muxe.advancedtouristmap.routing.Route.java
org.muxe.advancedtouristmap.sourcefiles.AddressFile.java
org.muxe.advancedtouristmap.sourcefiles.FileManagerActivity.java
org.muxe.advancedtouristmap.sourcefiles.FileManager.java
org.muxe.advancedtouristmap.sourcefiles.MapBundle.java
org.muxe.advancedtouristmap.sourcefiles.MapFile.java
org.muxe.advancedtouristmap.sourcefiles.PoiFile.java
org.muxe.advancedtouristmap.sourcefiles.RoutingFile.java
org.muxe.advancedtouristmap.sourcefiles.SourceFile.java
org.muxe.advancedtouristmap.wikipedia.AbstractWikiArticle.java
org.muxe.advancedtouristmap.wikipedia.ArticleRetrieverFactory.java
org.muxe.advancedtouristmap.wikipedia.ArticleRetriever.java
org.muxe.advancedtouristmap.wikipedia.GeonamesRetriever.java
org.muxe.advancedtouristmap.wikipedia.OnlineWikiArticle.java
org.muxe.advancedtouristmap.wikipedia.WikiArticleInterface.java
org.muxe.advancedtouristmap.wikipedia.WikilocationRetriever.java