SiriusMap.java :  » UnTagged » sirius-android » org » mips » Sirius » ui » Android Open Source

Android Open Source » UnTagged » sirius android 
sirius android » org » mips » Sirius » ui » SiriusMap.java
package org.mips.Sirius.ui;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;

import org.mips.R;
import org.mips.Sirius.components.Line;
import org.mips.Sirius.components.StopMonitoring;
import org.mips.Sirius.components.StopPoint;
import org.mips.Sirius.components.Vehicle;
import org.mips.Sirius.provider.ProviderException;
import org.mips.Sirius.provider.TransportInformationProvider;
import org.mips.Sirius.provider.SIRI.SIRIProvider;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

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;

/*
 * Main class
 * Implements the user interface and binds it with the needed components
 */
public class SiriusMap extends MapActivity implements LocationListener {

  /*
   * Private fields
   */

  // user interface
  private MapView map;
  private MapController mapController;
  public static final int DIALOG_FATAL_ERROR_ID = 1;
  public static final int DIALOG_NETWORK_ERROR_ID = 2;
  public static final int DIALOG_GPS_ERROR_ID = 3;
  public static final int DIALOG_LOADING = 4;
  public static final String MENU_FIND_ME = "Find me";
  public static final String MENU_TOGGLE_MAP = "Toggle satellite";
  private GeoPoint lastKnownLocation = null;
  private HashMap<String, Integer> linesColouring;
  private SiriusLoadingDialog loadingDialog;
  private SiriusLoadingDialog tapLoadingDialog;
  private SiriusStopMonitoringDialog smDialog;

  // components
  private LocationManager locationManager;
  private TransportInformationProvider provider;

  // default configuration
  private final int DEFAULT_ZOOM_LEVEL = 15;
  private final String providerURL = "http://mips42.altervista.org/etc/siri_feed.php";
  private final int requestDelay = 5000;

  // constants
  private final String LINES_DRAWN = "lines_drown";
  private final String STOPPOINTS_DRAWN = "stoppoints_drown";
  private final String VEHICLES_DRAWN = "vehicles_drown";

  /*
   * Constructor
   */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    linesColouring = new HashMap<String, Integer>();

    // create map
    map = createMap();
    if (map == null) {
      Log.d("debug", "creating map failed");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }

    // set up a default transport information source
    // FIXME: don't hardcode
    try {
      provider = new SIRIProvider(new URL(providerURL), requestDelay);
    } catch (MalformedURLException e) {
      Log.d("debug", "malformed URLs in config");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }
    if (provider == null) {
      Log.d("debug", "creating information provider failed");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }

    // create a location manager, a GPS listener and bind them
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    if (locationManager == null) {
      Log.d("debug", "creating location manager failed");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
        0, this);

    // add an overlay showing where the user is
    MyLocationOverlay userLocationOverlay = new FixedMyLocationOverlay(
        this, map);
    userLocationOverlay.enableMyLocation();
    userLocationOverlay.enableCompass();
    map.getOverlays().add(userLocationOverlay);

    Drawable defaultMarker;
    try {
      defaultMarker = MarkerFactory.createDefaultMarker();
    } catch (SiriusUIException e) {
      Log.d("debug", "no internet connectivity");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }

    // add an overlay showing the transit map (lines)
    LinesMapOverlay linesOverlay = new LinesMapOverlay(defaultMarker);
    if (linesOverlay == null) {
      Log.d("debug", "creating lines overlay failed");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }
    map.getOverlays().add(linesOverlay); // place it on top of the map

    // add an overlay showing where buses are
    VehicleMapOverlay busOverlay = new VehicleMapOverlay(defaultMarker);
    if (busOverlay == null) {
      Log.d("debug", "creating bus overlay failed");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }
    map.getOverlays().add(busOverlay); // place it on top of the map

    // add an overlay showing where stops are
    StopPointsMapOverlay stopOverlay = new StopPointsMapOverlay(
        defaultMarker);
    if (stopOverlay == null) {
      Log.d("debug", "creating stop overlay failed");
      showDialog(DIALOG_FATAL_ERROR_ID);
      return;
    }
    map.getOverlays().add(stopOverlay); // place it on top of the map

    // set map as current view
    setContentView(map);

    // prepare dialogs
    ArrayList<String> tokens = new ArrayList<String>();
    tokens.add(LINES_DRAWN);
    tokens.add(STOPPOINTS_DRAWN);
    tokens.add(VEHICLES_DRAWN);
    loadingDialog = new SiriusLoadingDialog(this, tokens);

    smDialog = new SiriusStopMonitoringDialog(this);

    loadingDialog.show();

  }

  /*
   * Creates the map, i.e. the main user interface
   */
  private MapView createMap() {
    // FIXME: generate "release" API key
    MapView map = new MapView(this, getString(R.string.maps_api_key));
    mapController = map.getController();
    mapController.setZoom(DEFAULT_ZOOM_LEVEL); // set a default zoom level
    map.setSatellite(true);
    map.setClickable(true);
    map.setBuiltInZoomControls(true); // allow user to change zoom level

    return map;
  }

  /*
   * Called the first time a certain dialog is called
   */
  @Override
  protected Dialog onCreateDialog(int dialogId) {
    Dialog dialog;
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setCancelable(false);

    switch (dialogId) {

    case DIALOG_FATAL_ERROR_ID:

      builder.setMessage("Sorry, I couldn't boot and I'm dying.");

      builder.setNeutralButton("Ok",
          new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              finish();
            }
          });
      dialog = builder.create();
      break;
    case DIALOG_NETWORK_ERROR_ID:

      builder
          .setMessage("A network error has occured. Please try again.");
      builder.setNeutralButton("Ok",
          new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              dialog.dismiss();
            }
          });
      dialog = builder.create();
      break;
    case DIALOG_GPS_ERROR_ID:

      builder.setMessage("Your current location is not yet available");
      builder.setNeutralButton("Ok",
          new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
              dialog.dismiss();
            }
          });
      dialog = builder.create();
      break;
    case DIALOG_LOADING:

      SiriusLoadingDialog sldialog = new SiriusLoadingDialog(this);
      sldialog.setMessage("Loading");
      dialog = sldialog;
      break;
    default:
      dialog = null;
      Log.d("debug", "unknown dialog requested");
      break;
    }

    if (dialog == null) {
      Log.d("debug", "building alert dialog failed");
    }

    return dialog;
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(MENU_FIND_ME);
    menu.add(MENU_TOGGLE_MAP);
    return true;
  }

  @Override
  public boolean onMenuItemSelected(int featureId, MenuItem item) {
    if (item.getTitle() == MENU_FIND_ME) {
      if (lastKnownLocation == null) {
        showDialog(DIALOG_GPS_ERROR_ID);
      } else {
        map.getController().setCenter(lastKnownLocation);
      }
    } else if (item.getTitle() == MENU_TOGGLE_MAP) {
      map.setSatellite(!map.isSatellite());
    }
    return true;
  }

  /*
   * Tell the Maps API we're not using route information (yet)
   */
  @Override
  protected boolean isRouteDisplayed() {
    return false;
  }

  private class VehicleMapOverlay extends SiriusOverlay {

    public VehicleMapOverlay(Drawable defaultMarker) {
      super(defaultMarker);
      this.populate();
    }

    @Override
    public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
        long when) {
      super.draw(canvas, mapView, shadow);

      synchronized (provider) {
        ArrayList<Vehicle> vehicles;

        try {
          vehicles = provider.getRealtimeVehicleInformation();
        } catch (ProviderException pe) {
          Log.d("debug",
              "Failed to retrieve real-time vehicle information"
                  + pe.getCause().getMessage());
          return true;
        }

        if ((vehicles == null) || linesColouring.isEmpty())
          return true;

        this.items = new ArrayList<OverlayItem>();

        // draw markers for each vehicle
        for (Vehicle vehicle : vehicles) {
          OverlayItem item = new OverlayItem(
              vehicle.getCoordinates(), "", "");

          // get a marker for the vehicle
          Drawable marker;
          try {
            marker = MarkerFactory.createVehicleMarker(vehicle
                .getName(), Colouring
                .getHTMLColour(linesColouring.get(vehicle
                    .getLineReference())));
          } catch (SiriusUIException e) {
            Log.d("debug", "no internet connectivity");
            showDialog(DIALOG_FATAL_ERROR_ID);
            return false;
          }
          ItemizedOverlay.boundCenterBottom(marker);
          item.setMarker(marker);
          this.items.add(item);
        }

        this.populate();

        loadingDialog.notifyReady(VEHICLES_DRAWN);

        return true;
      }
    }
  }

  private class StopPointsMapOverlay extends SiriusOverlay {

    public StopPointsMapOverlay(Drawable defaultMarker) {
      super(defaultMarker);
      this.populate();
    }

    @Override
    public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
        long when) {
      super.draw(canvas, mapView, shadow);

      synchronized (provider) {
        ArrayList<StopPoint> stopPoints;

        try {
          stopPoints = provider.getStaticStopPointsInformation();
        } catch (ProviderException pe) {
          Log.d("debug", "Failed to retrieve stops information");
          return true;
        }

        if (stopPoints == null)
          return true;

        this.items = new ArrayList<OverlayItem>();
        // draw markers for each stop
        for (StopPoint stop : stopPoints) {
          OverlayItem item = new SiriusOverlayItem(stop, stop
              .getCoordinates(), stop.getName(), stop
              .getReference());
          // get a marker for the stop
          Drawable marker;
          try {
            marker = MarkerFactory.createStopMarker(stop
                .getReference());
          } catch (SiriusUIException e) {
            Log.d("debug", "no internet connectivity");
            showDialog(DIALOG_FATAL_ERROR_ID);
            return false;
          }
          ItemizedOverlay.boundCenterBottom(marker);
          item.setMarker(marker);
          this.items.add(item);
        }

        this.populate();

        loadingDialog.notifyReady(STOPPOINTS_DRAWN);

        return false;
      }
    }

    @Override
    public boolean onTap(final int x) {
      SiriusOverlayItem tappedItem = (SiriusOverlayItem) this
          .createItem(x);
      if (tappedItem == null) {
        Log.d("tap", "Tapped item with index " + x + " not found");
        return false;
      }

      Log.d("tap", "Tapped item with index " + x + ": "
          + tappedItem.getTitle());

      tapLoadingDialog = new SiriusLoadingDialog(SiriusMap.this);
      tapLoadingDialog.show();

      handler.postDelayed(new Runnable() {

        @Override
        public void run() {

          SiriusOverlayItem tappedItem = (SiriusOverlayItem) StopPointsMapOverlay.this
              .createItem(x);

          smDialog.setDismissable(tapLoadingDialog);

          try {
            StopMonitoring stopMonitoring = provider
                .getRealtimeStopPointInformation(tappedItem
                    .getStop());
            tappedItem.getStop().setLastMonitoring(stopMonitoring);

            smDialog.setStop(tappedItem.getStop());

          } catch (ProviderException pe) {
            Log.d("tap",
                "Failed to retrieve stop monitoring information for stop "
                    + tappedItem.getStop());
            smDialog.setStop(null);
            handler.sendMessage(Message.obtain(handler, 0,
                DIALOG_NETWORK_ERROR_ID, 0));
          }

        }
      }, 500);

      return true;
    }
  }

  private class LinesMapOverlay extends SiriusOverlay {

    public LinesMapOverlay(Drawable defaultMarker) {
      super(defaultMarker);
      this.populate();
    }

    @Override
    public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
        long when) {
      super.draw(canvas, mapView, shadow);

      synchronized (provider) {
        ArrayList<Line> lines;

        try {
          lines = provider.getStaticLinesInformation();
        } catch (ProviderException pe) {
          Log.d("debug", "Failed to retrieve lines information");
          return true;
        }

        if (lines == null)
          return true;

        this.items = new ArrayList<OverlayItem>();

        for (Line line : lines) {

          linesColouring.put(line.getReference(), new Integer(
              Colouring.getColour(lines.indexOf(line), lines
                  .size())));
          Paint paint = new Paint();
          paint.setColor(linesColouring.get(line.getReference()));
          paint.setAlpha(80);
          paint.setStrokeWidth(5f);
          paint.setStyle(Paint.Style.STROKE);
          paint.setStrokeJoin(Paint.Join.ROUND);

          Path path = new Path();

          Point oldPoint = null;
          // draw the line map
          for (GeoPoint wayPoint : line.getStopPointsPath()) {
            Point point = new Point();
            mapView.getProjection().toPixels(wayPoint, point);

            if (oldPoint != null) {
              path.lineTo(point.x, point.y);
              oldPoint = point;
            } else {
              path.moveTo(point.x, point.y);
              oldPoint = point;
            }
          }

          canvas.drawPath(path, paint);
        }

        loadingDialog.notifyReady(LINES_DRAWN);

        return false;
      }
    }
  }

  /*
   * Called whenever the GPS position of the user changes
   */
  public synchronized void onLocationChanged(Location newLocation) {

    Log.d("debug", "Location is now: " + newLocation.getLatitude() + " "
        + newLocation.getLongitude());

    int newLatitude = (int) (newLocation.getLatitude() * 1000000);
    int newLongitude = (int) (newLocation.getLongitude() * 1000000);
    GeoPoint newLocationPoint = new GeoPoint(newLatitude, newLongitude);

    if (newLocationPoint != lastKnownLocation) {
      lastKnownLocation = newLocationPoint;

      Log.d("debug", "Centering on: " + newLocationPoint.getLatitudeE6()
          + " " + newLocationPoint.getLongitudeE6());
    }

  }

  @Override
  public void onProviderDisabled(String arg0) {
  }

  @Override
  public void onProviderEnabled(String provider) {
  }

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

  private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      Log.d("tap", "handler " + msg.obj);

      SiriusMap.this.showDialog(msg.arg1);
    }
  };
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.